Proposal: 1) Number (integer or decimal) to Array 2) Array to Number (integer or decimal)

Jeremy Martin jmar777 at gmail.com
Thu Mar 7 20:54:50 UTC 2019

```Can you explain the motivation for this proposal?

At first blush, this seems like an incredibly arbitrary pair of value
conversion utilities. Are there real world applications for this?

On Thu, Mar 7, 2019 at 3:43 PM guest271314 <guest271314 at gmail.com> wrote:

>
>
> ---------- Forwarded message ---------
> From: guest271314 <guest271314 at gmail.com>
> Date: Thu, Mar 7, 2019 at 8:35 PM
> Subject: Proposal: 1) Number (integer or decimal) to Array 2) Array to
> Number (integer or decimal)
> To: <es-discuss at mozilla.org>
>
>
> Original concept: Integer or decimal to array and array to decimal or
> integer https://codegolf.meta.stackexchange.com/a/17223
>
> Proof of concept (with bugs)
>
> function numberToArray(n) {
>
>   if (Math.abs(n) == 0 || Math.abs(n) == -0) {
>     return [n]
>   }
>
>   const r = [];
>
>   let [
>     a, int = Number.isInteger(a), d = g = [], e = i = 0
>   ] = [ n || this.valueOf()];
>
>   if (!int) {
>     let e = ~~a;
>     d = a - e;
>     do {
>       if (d < 1) ++i;
>       d *= 10;
>     } while (!Number.isInteger(d));
>   }
>
>   for (; ~~a; r.unshift(~~(a % 10)), a /= 10);
>
>   if (!int) {
>     for (; ~~d; g.unshift(~~(d % 10)), d /= 10);
>     g[0] = g[0] * (1 * (10 ** -i))
>     r.push(...g);
>   }
>
>   return r;
> }
> function arrayToNumber(a) {
>   if ((Math.abs(a[0]) == 0 || Math.abs(a[0]) == -0)
>      && a.length == 1) return a[0];
>   const [
>     g, r = x => x.length == 1
>                 ? x[0]
>                 : x.length === 0
>                   ? x
>                   : x.reduce((a, b) => a + b)
>     , b = a.find(x => g(x)), p = a.findIndex(x => g(x))
>   ] = [x => !Number.isInteger(x)];
>
>   let [i, j] = [b ? p : a.length, -1];
>
>   return a.length === 1
>     ? a[0]
>     : b && p
>       ? r(a.slice(0, p).map(x => i ? x * (10 ** --i) : x))
>         + (a[p] + (a[p + 1] !== undefined
>           ? r(a.slice(p + 1).map(x => x * (10 ** --j)))
>           : 0))
>       : r(a.map(x => i ? x * (10 ** --i) : x))}
> let tests = [0, 200, 100.00015, -123, 4.4, 44.44, -0.01, 123
>             , 2.718281828459, 321.7000000001, 809.56
>             , 1.61803398874989, 1.999, 100.01, 545454.45
>             , -7, -83.782, 12, 1.50, 100.0001];
> let arrays = tests.map(n => [...numberToArray(n)]);
> let numbers = arrays.map(n => arrayToNumber(n));
>
> console.log({tests, arrays, numbers});
>
>
> and working code (fixed bugs) by Stack Overflow user Shidersz
> https://stackoverflow.com/users/10366495/shidersz
>
> Method numberToArray():
>
> I have been working some time on your implementation, and thinked to first
> analyze the numberToArray() method. To start, I have decided to create a
> method for analyze a decimal number and return statistics about it,
> basically, the information you where getting from this part of your code:
>
> if (!int) {
>     let e = ~~a;
>     d = a - e;
>     do {
>         if (d < 1) ++i;
>         d *= 10;
>     } while (!Number.isInteger(d));}
>
> The method I have made on is the next one (will be used inside
> numberToArray()) and basically gets the next information:
>
> *1)* Integer section (iSection) of the decimal number (as integer).
>
> *2)* Decimal section (dSection) of the decimal number (as integer).
>
> *3)* Number of digits after the dot (dDigits).
>
> *4)* Number of leading zeros after the dot (dZeros).
>
> function getDecimalStats(dec){
>     let dDigits = 0, test = dec, factor = 1, dZeros = 0;
>
>     // Store the integer section of the decimal number.
>
>     let iSection = ~~dec;
>
>     // Get the numbers of digits and zeros after the comma.
>
>     while (!Number.isInteger(test))
>     {
>         factor = Math.pow(10, ++dDigits);
>         test = dec * factor;
>         dZeros += Math.abs(test - (iSection * factor)) < 1 ? 1 : 0;
>     }
>
>     // Store the decimal section as integer.
>
>     let dSection = test - (iSection * factor);
>
>     // Return an object with all statistics.
>
>     return {iSection, dSection, dZeros, dDigits};};
>
> console.log(getDecimalStats(10.001));
> console.log(getDecimalStats(-210.1));
> console.log(getDecimalStats(-0.00001));
>
> Of course, if you dislike, you can put this same logic directly inside
> numberToArray() method. So, after making the previous function, I have
> done some reorganization on your code and added some commentaries to helps
> me understand what you where doing. Finally, and after adapted your code, I
> have found that the wrong mapping to the arrays was mostly because the
> arithmetic precision when operating with float number. After investigate
> mathematical correction factor (it is commented on the code when it is
> applied). All in all, and until this time, I have come with the next
> solution to the numberToArray() method.
>
> function getDecimalStats(dec){
>     let dDigits = 0, test = dec, factor = 1, dZeros = 0;
>
>     // Store the integer section of the decimal number.
>
>     let iSection = ~~dec;
>
>     // Get the numbers of digits and zeros after the comma.
>
>     while (!Number.isInteger(test))
>     {
>         factor = Math.pow(10, ++dDigits);
>         test = dec * factor;
>         dZeros += Math.abs(test - (iSection * factor)) < 1 ? 1 : 0;
>     }
>
>     // Store the decimal section as integer.
>
>     let dSection = test - (iSection * factor);
>
>     // Return an object with all statistics.
>
>     return {iSection, dSection, dZeros, dDigits};};
> function numberToArray(n){
>     let r = [];
>
>     if (Math.abs(n) == 0)
>         return [n];
>
>     let [a, int = Number.isInteger(a), g = []] = [n || this.valueOf()];
>
>     // Get the stats of the decimal number.
>
>     let {dSection, dZeros} = getDecimalStats(a);
>
>     // Push the integer part on the array.
>
>     for (; ~~a; r.unshift(~~(a % 10)), a /= 10);
>
>     // Push the decimal part on the array.
>
>     if (!int)
>     {
>         // Push decimal digits on temporal array "g".
>         for (; ~~dSection; g.unshift(~~(dSection % 10)), dSection /= 10);
>
>         // Define the correction factor for the next operation.
>         let cf = 10 ** (++dZeros);
>
>         // Map g[0] to a decimal number and push elements on the array.
>         g[0] = (g[0] * cf) * ((10 ** -dZeros) * cf) / (cf * cf);
>         r.push(...g);
>     }
>
>     return r;}
> let tests = [0, 200, 100.00015, -123, 4.4, 44.44, -0.01, 123,2.718281828459, 321.7000000001, 809.56,1.61803398874989, 1.999, 100.01, 545454.45,-7, -83.782, 12, 1.50, 100.0001];
> let arrays = tests.map(n => [...numberToArray(n)]);
> console.log({tests, arrays});
>
> Method arrayToNumber():
>
> For this one I decided to go on my own (actually ignoring your current
> logic). The next approach will use the previously mentioned
> getDecimalStats() and mainly the Array::reduce()
> <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce>
> :
>
> function getDecimalStats(dec){
>     let dDigits = 0, test = dec, factor = 1, dZeros = 0;
>
>     // Store the integer section of the decimal number.
>
>     let iSection = ~~dec;
>
>     // Get the numbers of digits and zeros after the comma.
>
>     while (!Number.isInteger(test))
>     {
>         factor = Math.pow(10, ++dDigits);
>         test = dec * factor;
>         dZeros += Math.abs(test - (iSection * factor)) < 1 ? 1 : 0;
>     }
>
>     // Store the decimal section as integer.
>
>     let dSection = test - (iSection * factor);
>
>     // Return an object with all statistics.
>
>     return {iSection, dSection, dZeros, dDigits};};
> function arrayToNumber(a){
>     // Get the index of the first decimal number.
>
>     let firstDecIdx = a.findIndex(
>         x => Math.abs(x) > 0 && Math.abs(x) < 1
>     );
>
>     // Get stats about the previous decimal number.
>
>     let {dZeros} = getDecimalStats(firstDecIdx >= 0 ? a[firstDecIdx] : 0);
>
>     // Normalize firstDecIdx.
>
>     firstDecIdx = firstDecIdx < 0 ? a.length : firstDecIdx;
>
>     // Reduce the array to get the number.
>
>     let number = a.reduce(
>         ({num, dIdx, dPow}, n, i) =>
>         {
>             // Define the correction factor.
>             let cf = 10 ** (dPow + i - dIdx);
>
>             if (i < dIdx)
>                num += n * (10 ** (dIdx - i - 1));
>             else if (i === dIdx)
>                num = ((num * cf) + (n * cf)) / cf;
>             else
>                num = ((num * cf) + n) / cf;
>
>             return {num, dIdx, dPow};
>         },
>         {num: 0, dIdx: firstDecIdx, dPow: ++dZeros}
>     );
>
>     return number.num;}
> let tests = [
>     [0],
>     [2, 0, 0],
>     [1, 0, 0, 0.0001, 5],
>     [-1, -2, -3],
>     [4, 0.4],
>     [4, 4, 0.4, 4],
>     [-0.01],
>     [1, 2, 3],
>     [2, 0.7, 1, 8, 2, 8, 1, 8, 2, 8, 4, 5, 9],
>     [3, 2, 1, 0.7, 0, 0, 0, 0, 0, 0, 0, 0, 1],
>     [8, 0, 9, 0.5, 6],
>     [1, 0.6, 1, 8, 0, 3, 3, 9, 8, 8, 7, 4, 9, 8, 9],
>     [1, 0.9, 9, 9],
>     [1, 0, 0, 0.01],
>     [5, 4, 5, 4, 5, 4, 0.4, 5, 0],
>     [-7],
>     [-8,-3, -0.7, -8, -2],
>     [1, 2],
>     [1, 0.5],
>     [1, 0, 0, 0.0001]];
> let numbers = tests.map(n => arrayToNumber(n));
> console.log(numbers);
>
> Finally, I hope you can value my efforts, and obviously there can be a lot
> of improvements to my solution (so, any recommendation is welcome). For
> example, there are currently none or few checks for safety.
>
>
> Number (integer or decimal) to array, array to number (integer or decimal)
> without using strings https://stackoverflow.com/q/54433007
>
> *Context and use cases:*
>
> available in some browsers, though not a BigDecimal. The conversion from
> integer or decimal to array and array to integer or decimal should be
> possible using the JavaScript programming language. The input and output
> should not need to be converted to a string during the procedure.
>
> Ability to adjust *nth* digit of an integer or decimal by adjusting
> decimal or integer at *nth* index of array, to try to solve OEIS A217626
> <https://oeis.org/A217626> directly, for example
>
> ~~(128.625*9*1.074)//1243~~(128.625*9*1.144)//1324
>
> where the decimal portion can be manipulated by referencing the index of
> an array, then converting the array back to a number.
>
> Specification (WIP):
>
> [...Math.E] -> [2, 0.7, 1, 8, 2, 8, 1, 8, 2, 8, 4, 5, 9] -> 2.718281828459
>
> Input <----------> Output
> -123               [-1,-2,-3]4.4                [4,0.4]44.44              [4,4,0.4,4]-0.01              [-0.01]123                [1,2,3]200                [2,0,0]2.718281828459     [2,0.7,1,8,2,8,1,8,2,8,4,5,8,9]321.7000000001     [3,2,1,0.7,0,0,0,0,0,0,0,0,1]809.56             [8,0,9,0.5,6]1.61803398874989   [1,0.6,1,8,0,3,3,9,8,8,7,4,9,8,9]1.999              [1,0.9,9,9]100.01             [1,0,0,0.01]545454.45          [5,4,5,4,5,4,0.4,5]-7                 [-7]-83.782            [-8,-3,-0.7,-8,-2]1.5                [1,0.5]100.0001           [1,0,0,0.0001]
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>

--
Jeremy Martin
661.312.3853