Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do floating point operations display different in some languages?

I have read these:

  • Why Are Floating Point Numbers Inaccurate?
  • http://floating-point-gui.de/

They explain "how". I'd like to know why it's different across these languages. I expected similar results given the same input.

test.js

#!/usr/bin/env node

var nine = 9.0;
var pointOhOhOne = 0.001;
var result = nine * pointOhOhOne;
console.log(result);

test.java

public class test {

  public static void main(String[] argv) {
    double nine = 9.0d;
    double pointOhOhOne = 0.001d;
    double result = nine * pointOhOhOne;
    System.out.println(result);
  }

}

test.c

#include "stdio.h"

int main() {
  double nine = 9.0;
  double pointOhOhOne = 0.001;
  double result = nine * pointOhOhOne;
  printf("%f", result);
}

test.rb

#!/usr/bin/env ruby

nine = 9.0
pointOhOhOne = 0.001
result = nine * pointOhOhOne

print result

test.py

#!/usr/bin/env python

nine = 9.0
pointOhOhOne = 0.001
result = nine * pointOhOhOne

print result

results:

ruby     0.009000000000000001
python   0.009
node     0.009000000000000001
java     0.009000000000000001
c        0.009000

gist: https://gist.github.com/reklis/6694ad5fb01991a79a1a

like image 434
slf Avatar asked Oct 02 '14 20:10

slf


People also ask

Why are floating points inaccurate in Python?

It's a problem caused when the internal representation of floating-point numbers, which uses a fixed number of binary digits to represent a decimal number. It is difficult to represent some decimal number in binary, so in many cases, it leads to small roundoff errors.

Why are floating point numbers inaccurate in Javascript?

Because often-times, they are approximating rationals that cannot be represented finitely in base 2 (the digits repeat), and in general they are approximating real (possibly irrational) numbers which may not be representable in finitely many digits in any base.

Why is floating point inaccurate?

Floating-point decimal values generally do not have an exact binary representation due to how the CPU represents floating point data. For this reason, you may experience a loss of precision, and some floating-point operations may produce unexpected results.

What are floating points operations?

Specific to floating-point numbers, a floating-point operation is any mathematical operation (such as +, -, *, /) or assignment that involves floating-point numbers (as opposed to binary integer operations). Floating-point numbers have decimal points in them.


2 Answers

In C on my system:

printf("%.18f\n", result);

0.009000000000000001

In Python on my system:

print("%.18f" % result)

0.009000000000000001

C or Python like other languages limit the number of decimal digits by default with their print functions.

like image 178
ouah Avatar answered Dec 17 '22 22:12

ouah


@ouah establishes that the languages are all behaving the same. My answer aims to explain why they appear different. The only two languages that have "different" output are C and Python.

Clearly, every language besides C and Python is just printing out the float value to as many decimal places as it can.

C is easy to explain. You use printf("%f", result), without specifying an explicit precision value. Per the C standard, the precision of the f specifier defaults to 6. Thus, exactly six decimal places are printed out, which is what you see. As @ouah notes, setting the precision to 18 will yield the "expected" output. This is lossy: doubles that differ past the 7th decimal place will be printed out identically, and so the output of %f cannot be relied on to exactly reconstruct the original float.

Python is a bit trickier. Python 3.1 introduced a new floating-point repr algorithm, based on work by David Gay. The Python issue corresponding to the feature is here: http://bugs.python.org/issue1580. This feature was backported to Python 2.7 as well.

The intention of this new feature was to both reduce confusion over floating point (though that is dubiously useful), and more importantly to provide more human-readable, shorter representations of floating point numbers without affecting round-trip behaviour; that is, float(repr(x)) is always equal to x, even if repr(x) is shortened due to this algorithm. So, the algorithm manages to produce a shorter floating-point representation while remaining "lossless": win-win!

The official description says this much:

The new algorithm for repr(1.1) is smarter and returns '1.1'. Effectively, it searches all equivalent string representations (ones that get stored with the same underlying float value) and returns the shortest representation.

like image 44
nneonneo Avatar answered Dec 17 '22 22:12

nneonneo