Earlier quoted context omitted.
You can get a larger error than that using one operation. fn main() { let x: f64 = 9007199254740992.0; assert_eq!(x + 1.0, x); }
You are absolutely right. When adding numbers with large magnitudes differences (around 10^17 I think) it might exceed the format precision. I should have taken that in account when defining the error boundaries. In dollars, you start having issues with cents when working with a tens of trillions. For the vast majority of people this won't be an issue.
0.30000000000000004
381–390 of 422 posts
Re: 0.30000000000000004
#382Earlier quoted context omitted.
And that roughly captures the spot where I was seeing doubles used. Yes, they could have used fixed point. I am guessing that what happened is that someone who had thought way more deeply about this than I ever needed to (I worked on the accounting side, where, yep, we always used decimals) either determined that, where the modeling was concerned, floating point errors were not worth worrying about, or estimated that…
To see 0.1 error using _double_ you have to do at least 2*10^17 operations (assuming the worst case scenario and no subnormals). If you are working with such huge numbers, 0.1 cents is probably a cost you are willing to pay to avoid expending thousands in a software solution. The saving with power saving using a floating point is likely greater than power your computers will have to expend to get a precise solution.
I'm too lazy to figure out a specific example, but sets of numbers where doubles round up and decimals round down (or vice versa) aren't terribly uncommon.
Re: 0.30000000000000004
#383That said, it's one of my favorite trivia gotchas.
Re: 0.30000000000000004
#384Earlier quoted context omitted.
In a language like Java, all these factors are specified and fully deterministic.
False. Floating-point arithmetic in Java is generally nondeterministic. You will notice that the strictfp keyword exists and is off by default.
Secondly, on mainstream implementations, strictfp is already documented the same as default! They're planning to remove it anyway as it's a no-op in almost all cases.
See JEP 306.
Re: 0.30000000000000004
#385Re: 0.30000000000000004
#386Earlier quoted context omitted.
My day job is high performance financial model implementation. Floats storing dollar amounts are the norm for predictions. Operating on values that are linear combinations of integer fractions multiplied by irrational constants (such as Euler’s number) is perfectly possible, but it’s much more performant to be aware of floating point epsilon when writing modeling code.
Financial models are predictive, they don't have to be accurate to a penny, right? Unlike processing actual money people own. (I do some work with predictive simulations about money, but outside finance, and there we care that the result has accurate order of magnitude. Floats were used extensively in the project; I actually upgraded them to doubles for the sake of handling larger order of magnitude spans.)
Re: 0.30000000000000004
#387Earlier quoted context omitted.
Currency in banking is handled with bigints. Not rationals, just bigints of the smallest unit (i.e., 1 cent). This forces you to order operations so that divisions are done last or not at all.
The bigint you describe is just a poor man's rational, given that no computer architecture or mainstream language support them natively.
Re: 0.30000000000000004
#388Earlier quoted context omitted.
Bitcoin uses fixed-width unsigned integers. The smallest unit is 10^-8 of 1 Bitcoin, which is represented as just 1.
I like this approach. Is it compatible with the parent comment?
Re: 0.30000000000000004
#389Earlier quoted context omitted.
But it is correct. > It's easy to write a program that sums up 0.01 until the result is not equal to n * 0.01. It's not easy to do that if you use a floating point decimal type, like I recommended . For instance, using C#'s decimal, that will take you somewhere in the neighborhood of 10 to the 26 iterations. With a binary floating point number, it's less than 10.
That is simply not true. The C# decimal type doesn't accumulate errors when adding , unless you exceed its ~28 digits of precision. E.g. see here: https://rextester.com/RMHNNF58645
Precisely. That's why I specified ~ 10^26 addition operations.
Re: 0.30000000000000004
#390Earlier quoted context omitted.
Hear, hear! It would be great if javascript had any integral type that we could build decimals, rationals, arbitrarily-large integers and so on off. It’s technically doable with doubles if you really know what you’re doing, but it would be so much easier with an integral type.
ES does have an arbitrarily large integer type, BigInt. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
There are several BigInt libraries out there that you could use, though obviously this is not as convenient and even if they wrap BigInt when available will be less efficient.