6

Hello I know that computer is limited by number precision, and some numbers cannot be represented accurately in binary system. That’s why I'm asking why such comparison

(0.1*3) == 0.3

in Java language evaluates to false while in C it evaluates to true, for me the Java behavior is a little bit more intuitive. Any of provided answers does not answer my question why they have different behaviors, since both use IEEE 754 standard.

@update I was using ideone to test condition.

whd
  • 1,819
  • 1
  • 21
  • 52
  • i know how to compare it i wanna know why java and C behaviour in different way – whd Apr 05 '16 at 13:47
  • @Olaf the same expression returns true in Java and false in C - the op is asking why. I think it's a legitimate question that is not an exact duplicate of the question you linked to. – assylias Apr 05 '16 at 13:47
  • Also see [Why are floating point numbers inaccurate](http://stackoverflow.com/questions/21895756/why-are-floating-point-numbers-inaccurate). There's countless of duplicates for this question. – Lundin Apr 05 '16 at 13:49
  • (And likely the different compilers used different floating point standards) – Lundin Apr 05 '16 at 13:51
  • 4
    @Lundin the question is the opposite: why are the two numbers considered equal? – assylias Apr 05 '16 at 13:51
  • @assylias Because on one particular compiler it was possibly to display the floating point number exactly, and on another it was not. It is the same old [go read Goldberg](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) FAQ. – Lundin Apr 05 '16 at 13:53
  • @Ludin if I'm correct both C and Java uses IEEE 754 standard, if You provide such big document as answer, coudl You tell which chapter shoudl i read? – whd Apr 05 '16 at 14:07
  • 4
    @Lundin: I don't think they use different floating point standards. Simply because they very likely use the hardware FPU which only implements one standard (typically IEEE754). But they might use different rounding modes and other allowed variations in IEEE754. – too honest for this site Apr 05 '16 at 14:09
  • 2
    http://floating-point-gui.de/errors/comparison/ just remember floating-point is binary not decimal, don't expect it to work like in decimal, because none of 0.1 and 0.3 is representable in binary. [Is floating point math broken?](http://stackoverflow.com/q/588004/995714) – phuclv Apr 05 '16 at 14:14
  • 2
    Is there any guarantee different languages have to behave the same? There are also differences e.g. for integer overflow between languages. Some even have changed the behaviour of operations between different versions (e.g. signed integer division in C). – too honest for this site Apr 05 '16 at 14:16
  • 5
    C [doesn't guarantee IEEE-754](http://stackoverflow.com/q/6971886/995714) although all modern architectures use IEEE-754. Even [C codes running in the same machine might produce different results](http://stackoverflow.com/q/22710272/995714) because one may be run in x87 and the other in SIMD and that might be your case too. – phuclv Apr 05 '16 at 14:19
  • 1
    Disassemble the compiled C code and see what it does. FPU has 80 bits precision (x87 at least) comparing to 64 bits of the double type used by JVM. – Archie Apr 05 '16 at 15:04
  • 2
    @Archie: since `(0.1*3) == 0.3` is a constant expression, the compiled code should only contain the result, not any hint about how it has been calculated. Besides that, `0.1` and `0.3` both have an infinite number of digits in the binary system, thus `(0.1*3) == 0.3` will always be `false`, regardless of the number of bits, unless you change the rounding mode or do not check for an exact match with the `==` operator. – Holger Apr 05 '16 at 15:12
  • 1
    @Holger: OP claims that his C compiler produces `true`. I am not speculating on how this result was achieved though, just provide a plausible explanation. – Archie Apr 05 '16 at 15:19
  • 1
    @Archie: I don’t know which freedom C compilers have when evaluating constant expressions (but I know that Java compilers don’t have any). All I’m saying, is, calculating the same thing using 80 bits instead of 64 alone won’t make a difference. – Holger Apr 05 '16 at 15:23
  • 1
    @Holger: It makes the difference depending on whether the result is kept in the FPU registers or being rounded from 80 to 64 bits and dumped into memory before comparison. – Archie Apr 05 '16 at 15:26
  • 1
    @Archie: as I said, if you use rounding (in a different mode than the default “round to nearest”), it can make a difference. – Holger Apr 05 '16 at 15:32
  • You need to identify the C compiler, runtime environment and hardware used. – Raedwald Apr 06 '16 at 08:13

1 Answers1

2

Comparing floating-point values is notoriously imprecise.

For any given floating-point operation, you are guaranteed an accuracy only down to DBL_EPSILON / Double.Epsilon. Any bits that exist beyond this precision are artifacts of the arithmetic operations and should be ignored.

Different programs, and certainly different languages, will implement such comparisons differently (obviously). If you can manage to compare values to a specific accuracy, i.e., a specific number of bits within the representational range of the values (e.g., 52 bits or less for IEEE double-precision float), you stand a better chance of getting identical results.

Reference (added April 2016)

Here is the oft-cited explanation of floating-point numbers and how they behave:
What Every Computer Scientist Should Know About Floating-Point Arithmetic

David R Tribble
  • 11,918
  • 5
  • 42
  • 52