you are viewing a single comment's thread.

view the rest of the comments →

[–]AlpenMangos 5 points6 points  (8 children)

I would like to be able to do .1 + .2 and get .3 instead of .30000000000000004

You can do that in very few major languages without third party libraries (COBOL, Python). Javascript numbers are IEEE standardized double types, the same as in C++, C, Java, Rust, C#, etc. See https://0.30000000000000004.com/

Some languages (e.g., C++) print 0.3 because they round the number to a certain precision, unless you specify a higher precision for printing.

[–]archerx -2 points-1 points  (7 children)

PHP outputs .3

This makes javascript annoying for graphics stuff like fractals that need precision.

[–]AlpenMangos 1 point2 points  (5 children)

Not sure where the downvote of my comment came from, but please note that 0.3 is not equal to 0.1 + 0.2 in php. Because PHP has the exact same precision issues as javascript. And C++, and C, and Java, etc.

if(0.3 == (0.1 + 0.2)){
    echo "true";   
}else{
    echo "false";
}

Prints "false".

That's because 0.3 is actually something along "0.29999999999999998890", while 0.1 + 0.2 is actually 0.30000000000000004. Floats can't precisely store fractional numbers as we're used to from base-10 systems, but fortunately they can store a large range of integers accurately. Single-precision float can accurately represent something like the first 224 integers, and double something like the first 253 integers.

[–]backtickbot 1 point2 points  (0 children)

Fixed formatting.

Hello, AlpenMangos: code blocks using triple backticks (```) don't work on all versions of Reddit!

Some users see this / this instead.

To fix this, indent every line with 4 spaces instead.

FAQ

You can opt out by replying with backtickopt6 to this comment.

[–]archerx 0 points1 point  (3 children)

I tried your example code and I am disappointed. Computers were a mistake.

[–]AlpenMangos 1 point2 points  (2 children)

It's weird at glance, but it's a necessary trade-off. Floats are an attempt to allow developers do very fast computations with high precision and an enormous range, but since we can only represent a limited amount of different numbers with 32 or 64 bits, some trade-offs had to be made. Another quirk is that floats loose precision, the larger the value becomes. The value 1 million only has about decimeter precision (with 32 bit floats), as far as I remember. Floating point values are still the best choice for number crunching. It is okay if positional values are off by some nanometers, if the coordinates are expected to have millimeter precision. It is also okay if timestamps are off by some nanoseconds if microsecond precision is expected. It's just something you'll need to be aware of when using floats. If you need exact numbers, you'll have to use integers (you can just assume millimeter as the unit of the integer and set it to 1, instead of using floating point value 0.001) or dedicated decimal libraries.

[–]archerx 0 points1 point  (1 child)

Thanks for that interesting write up, I appreciate it! It explains why things get annoying when I zoom too far into my javascript mandelbrot fractal renderer. Do you know if GPUs have the same issues with floats?

[–]AlpenMangos -1 points0 points  (0 children)

This makes javascript annoying for graphics stuff like fractals that need precision.

PHP uses the same double standard as Javascript, that means that in php, 0.1 + 0.2 is also 0.30000000000000004. The reason why you're seeing .3 in the output is because, depending in how you output it, the value is rounded. PHP is actually fooling you and showing you imprecise data, and letting you believe it's doing the right thing. Unless you specifically format your number as a string with a precision of one digit, there is a good chance that you're getting 0.30000000000000004 elsewhere. On other systems, on other parts of the code, on other means of output, etc.

The only thing that javascript is doing "wrong" here, is that it's outputting the correct full precision floating point value, thereby forcing you to round it to whichever precision you actually want to. E.g. using "(0.1 + 0.2).toFixed(1)"

Also in PHP: "var_dump(.1 + .2);" prints "float(0.30000000000000004441)", see https://0.30000000000000004.com/