If only some of my proposals that were actually useful got this much attention
On Mon, 11 Mar 2019, 4:33 pm Jeremy Martin, <[email protected]> wrote: > With respect, it's still not clear how you want to interact with the array > of values once you've destructured a Float into your array format. > > If all you have is an array of single-digit numbers that represent the > values in the tenths/hundredths/etc. positions of the source number, how > does this actually circumvent the challenges of representing Decimal values > that aren't exactly representable as a Float? > > To illustrate this challenge, let's use the classic example we've all seen > hundreds of times: > > > .1 + .2 > 0.30000000000000004 > > For a long time, all the reading I would do about *why* this produced a > weird result would *sort* of make sense and *sort* of confuse me. That > is, I could understand *why* 3/10ths isn't representable as a Float, but > then I would get confused by the fact that I could type `.3` into a REPL, > and it would *actually work *(??!): > > > .3 > 0.3 > > I mean, who's lying? How come `.3` works fine when I just type it > straight in, and `.1 + .3` works just fine, but there's just these > specific cases like `.1 + .2` where all of a sudden `.3` decides not to > be representable again? > > I admit this is conjecture, but maybe that's part of the confusion > motivating this proposal? And maybe the idea is that if we can break `.1` > and `.2` into some sort of an array structure (e.g., [0, 1] and [0, 2]), then > we can add the individual parts as integers (giving us something like [0, > 3]) which we can then just convert back into a single numeric value at > the end as 0.3, and voila, no 0.30000000000000004 shenanigans? > > The problem is that this all builds on a fundamental misunderstanding of > what's going. Let's revisit the basic example of entering a value into the > REPL: > > > .3 > 0.3 > > This, as I stated earlier, contributed greatly to my own hangups in > understanding what was going on here. What I personally didn't understand > was that the `0.3` value you see above isn't actually the *Decimal* value > 0.3. It's just a *very* close approximation of 0.3. (so close, in fact, > that 0.3 is the *closest* Decimal value that it can be rounded to, so > that's what gets emitted). > > So, going back to our earlier example, why do we get a *different* output > when we're dealing with the result of a mathematical operation, as opposed > to getting the *same* very close approximation of 0.3 that we get when we > simply type it into the REPL? > > > .1 + .2 > 0.30000000000000004 > > The answer lies in the fact that 0.1 and 0.2 *also* can't be represented > exactly as Floats. Just like we saw with 0.3, we can type them into the > REPL and see a value that looks the exact same being emitted back at us: > > > .1 > 0.1 > > .2 > 0.2 > > ...but also like we saw with 0.3, they only *look* like accurate > representations. Once again, 0.1 and 0.2 are just the closest Decimal > values that the underlying Float values can be rounded to for display. > > This rounding behavior, then, is what causes us to get 0.30000000000000004 > when we add them together, because the *slight* rounding error with 0.1 > and the *slight* rounding error with 0.2 compound to result in a Float > that no longer rounds closer to 0.3, and instead closer to the "wrong" > Decimal value that we see emitted before. > > It's worth noting that this same behavior applies to, e.g., 0.1 + 0.3, even > though that *looks* like it produces the correct result of 0.4. In > reality, however, this is just a case where the rounding errors have the > effect of (almost) canceling each other out, such that the resulting Float > rounds closer to 0.4 than any other value for display purposes (despite > being only negligibly more accurate than our 0.30000000000000004 result > was). > > Ok, so why am I trying to explain all this? Because I'm trying to > illustrate why it sounds like this proposal doesn't actually solve the > problem that you want it to. Is it possible to standardize a system for > transformations and math operations like the following? > > const arg1 = numberToArray(0.1) // [0, 1] > const arg2 = numberToArray(0.2) // [0, 2] > > const arraySum = addArrayNumbers(arg1, arg2) // [0, 3] > > const result = arrayToNumber(arraySum) // 0.3 > > Sure, and at the very end, you actually get a value that *looks* right ( > 0.3, yay!). But *it's still not actually 0.3.* So what become the > motivation for this? You have a solution that, in terms of memory and CPU > cycles, is orders of magnitude more costly to calculate than `0.1 + 0.2` as > a plain JavaScript expression, and in return you get a result that is, *at > best*, infinitesimally more accurate than the alternative when carried > all the way out to the quadrillionths place or greater. > > Do you actually have a use case for mathematical operations that are fault > tolerant enough to represent Decimal values as Floats, but that fault > tolerance is sensitive to very, very specific rounding behavior at the > quadrillionths level? I can't even imagine what that use case would be. > > On Mon, Mar 11, 2019 at 10:06 AM guest271314 <[email protected]> > wrote: > >> JS numbers are specified to be in terms of IEEE-754 doubles, so tenths, >>> hundredths, and so on cannot be precisely represented. [1] So there is no >>> way to increase precision here beyond the above that Tab showed, assuming >>> each of those operations are accurate to the bit. >> >> >> Not sure what the message is trying to convey? The code at the first >> post already overcomes the issue of >> >> i % 1 // 0.5670000000000073 >> >> described by Tab. All of the input numbers are converted to array then >> back to number without losing any precision or adding more numbers to the >> input. >> >> The proposal suggests that each discrete digit of any number a user can >> get and set and be clearly defined with a consistent name, or reference. >> Converting the number to an array is a simple means of processing each >> digit independently. >> >> On Mon, Mar 11, 2019 at 10:41 AM Isiah Meadows <[email protected]> >> wrote: >> >>> JS numbers are specified to be in terms of IEEE-754 doubles, so tenths, >>> hundredths, and so on cannot be precisely represented. [1] So there is no >>> way to increase precision here beyond the above that Tab showed, assuming >>> each of those operations are accurate to the bit. >>> >>> [1]: >>> https://www.exploringbinary.com/why-0-point-1-does-not-exist-in-floating-point/ >>> On Sun, Mar 10, 2019 at 13:26 guest271314 <[email protected]> wrote: >>> >>>> So this would help with precision? >>>> >>>> >>>> To an appreciable degree, yes, without the scope of JavaScript >>>> floating-point number implementation. >>>> >>>> The gist of the proposal is to formalize, standardize, or whatever term >>>> specification writers want to use, the *naming* of each method or operation >>>> which can get and set each discrete digit of a number - without using >>>> String methods. >>>> >>>> For input >>>> >>>> 1234.567 >>>> >>>> Each digit has a formal name which developers can get and set, whether >>>> in an array, object or number format. >>>> >>>> On Sun, Mar 10, 2019 at 5:17 PM Michael Theriot < >>>> [email protected]> wrote: >>>> >>>>> So this would help with precision? >>>>> >>>>> On Sunday, March 10, 2019, guest271314 <[email protected]> wrote: >>>>> >>>>>> (If you really wanted this as an integer, it's not well-founded; .567 >>>>>>> isn't exactly representable as a double, so JS doesn't know that you >>>>>>> "meant" it to have only three digits after the decimal point, and >>>>>>> thus >>>>>>> want 567 as the answer. You'll instead get some very very large >>>>>>> integer that *starts with* 567, followed by a bunch of zeros, >>>>>>> followed >>>>>>> by some randomish digits at the end.) >>>>>> >>>>>> >>>>>> The code at the first post solves that problem. >>>>>> >>>>>> But the question is still "what would someone use this information >>>>>>> for?" >>>>>> >>>>>> >>>>>> That question has been answered several times in the posts above. >>>>>> This users' motivation was and is the ability to manipulate JavaScript >>>>>> floating-point numbers (which could be considered "broken", as you >>>>>> described above) in order to solve mathematical problems (in this case, >>>>>> directly calculating the *n*th lexicographic permutation) with the >>>>>> number or decimal being represented as an array, without having to be >>>>>> concerned with not getting the same value when the array is converted >>>>>> back >>>>>> to a number. >>>>>> >>>>>> Felipe Nascimento de Moura mentioned several other applications. >>>>>> >>>>>> The work has already been done. This proposal is essentially to >>>>>> standardize the naming conventions. Whether a Number method is used >>>>>> >>>>>> i.getTensMethod >>>>>> >>>>>> or an array is used >>>>>> >>>>>> arr["integer"] // 1234 >>>>>> >>>>>> or an object where values are arrays is used >>>>>> >>>>>> o["fraction"] // .567 >>>>>> >>>>>> Having mentioned Intl.NumberFormat earlier in the thread, if the >>>>>> issue devoting resources to a *new *proposal, Intl.NumberFormate can >>>>>> be extended; e.g. a rough draft in code >>>>>> >>>>>> function formatNumberParts(args) { >>>>>> return Object.assign({sign:0, fraction:[0], integer:[0]}, >>>>>> ...args.filter(({type}) => type === "integer" || type === "fraction" || >>>>>> type === "minusSign").map(({type, value}) => ({[type === "minusSign" ? >>>>>> "sign" : type]: type !== "minusSign" ? [...value].map(Number) : -1}))); >>>>>> } >>>>>> >>>>>> let number = -123; >>>>>> >>>>>> let formatter = new Intl.NumberFormat('en-US'); >>>>>> >>>>>> let res = formatter.formatToParts(number); >>>>>> >>>>>> formatNumberParts(res); >>>>>> >>>>>> If the concern is that the proposal would not be useful, consider >>>>>> what you would *name* various uses of Math.trunc and remainder >>>>>> operator used at your message? >>>>>> >>>>>> >>>>>> On Sun, Mar 10, 2019 at 3:58 PM Tab Atkins Jr. <[email protected]> >>>>>> wrote: >>>>>> >>>>>>> On Sat, Mar 9, 2019 at 11:10 AM Felipe Nascimento de Moura >>>>>>> <[email protected]> wrote: >>>>>>> > >>>>>>> > Personally, I don't think it would be THAT useful... >>>>>>> > but...I think there is something behind this proposal that makes >>>>>>> sense. >>>>>>> > >>>>>>> > I do believe it could be useful for developers to have an easier >>>>>>> access to number parts or characteristics. >>>>>>> > Perhaps something like: >>>>>>> > >>>>>>> > const i = 1234.567; >>>>>>> >>>>>>> Can you provide a scenario in which these would do something useful, >>>>>>> such that it would be worth adding them over just using the math >>>>>>> operations that already exist? >>>>>>> >>>>>>> > console.log( i.float ); // 567 >>>>>>> >>>>>>> i % 1 >>>>>>> >>>>>>> (If you really wanted this as an integer, it's not well-founded; .567 >>>>>>> isn't exactly representable as a double, so JS doesn't know that you >>>>>>> "meant" it to have only three digits after the decimal point, and >>>>>>> thus >>>>>>> want 567 as the answer. You'll instead get some very very large >>>>>>> integer that *starts with* 567, followed by a bunch of zeros, >>>>>>> followed >>>>>>> by some randomish digits at the end.) >>>>>>> >>>>>>> > console.log( i.abs ); // 1234 >>>>>>> >>>>>>> Math.trunc(i) >>>>>>> >>>>>>> > console.log( i.thousands ); // 1 >>>>>>> >>>>>>> Math.trunc(i / 1000) >>>>>>> >>>>>>> > console.log( i.million ); // 0 >>>>>>> >>>>>>> Math.trunc(i / 1e6) >>>>>>> >>>>>>> > console.log( i.hundred ); // 2 >>>>>>> >>>>>>> Math.trunc(i / 100) % 10 >>>>>>> >>>>>>> > console.log( i.hundreds ); // 12 >>>>>>> >>>>>>> Math.trunc(i / 100) >>>>>>> >>>>>>> > console.log( i.ten ); // 2 >>>>>>> >>>>>>> Math.trunc(i / 10) % 10 >>>>>>> >>>>>>> > console.log( i.tens ); // 123 >>>>>>> >>>>>>> Math.trunc(i / 10) >>>>>>> >>>>>>> > console.log( i.tenth ); // 5 >>>>>>> >>>>>>> Math.trunc(i % 1 * 10) % 10 >>>>>>> >>>>>>> > console.log( i.tenths ); // 5 >>>>>>> >>>>>>> Math.trunc(i % 1 * 10) >>>>>>> >>>>>>> > console.log( i.hundredth ); // 6 >>>>>>> >>>>>>> Math.trunc(i % 1 * 100) % 10 >>>>>>> >>>>>>> > console.log( i.hundredths ); // 56 >>>>>>> >>>>>>> Math.trunc(i % 1 * 100) >>>>>>> >>>>>>> >>>>>>> Some of these are easy to remember and use; others take some thinking >>>>>>> to deploy. But the question is still "what would someone use this >>>>>>> information for?", such that the benefit to developers is worth the >>>>>>> cost to all parties involved (spec writers, implementors, testers, >>>>>>> and >>>>>>> then developers having to navigate a larger stdlib). >>>>>>> >>>>>>> ~TJ >>>>>>> _______________________________________________ >>>>>>> es-discuss mailing list >>>>>>> [email protected] >>>>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>>>> >>>>>> _______________________________________________ >>>>> es-discuss mailing list >>>>> [email protected] >>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>> >>>> _______________________________________________ >>>> es-discuss mailing list >>>> [email protected] >>>> https://mail.mozilla.org/listinfo/es-discuss >>>> >>> _______________________________________________ >> es-discuss mailing list >> [email protected] >> https://mail.mozilla.org/listinfo/es-discuss >> > > > -- > Jeremy Martin > 661.312.3853 > @jmar777 <https://twitter.com/jmar777> / @j <https://stream.live/j> > > _______________________________________________ > es-discuss mailing list > [email protected] > https://mail.mozilla.org/listinfo/es-discuss >
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

