Why does (int)(33.46639 * 1000000) return 33466389

2020-06-08 03:29发布

问题:

(int)(33.46639 * 1000000) returns 33466389

Why does this happen?

回答1:

Floating point math isn't perfect. What every programmer should know about it.

Floating-point arithmetic is considered an esoteric subject by many people. This is rather surprising because floating-point is ubiquitous in computer systems. Almost every language has a floating-point datatype; computers from PCs to supercomputers have floating-point accelerators; most compilers will be called upon to compile floating-point algorithms from time to time; and virtually every operating system must respond to floating-point exceptions such as overflow. This paper presents a tutorial on those aspects of floating-point that have a direct impact on designers of computer systems. It begins with background on floating-point representation and rounding error, continues with a discussion of the IEEE floating-point standard, and concludes with numerous examples of how computer builders can better support floating-point.

...

Squeezing infinitely many real numbers into a finite number of bits requires an approximate representation. Although there are infinitely many integers, in most programs the result of integer computations can be stored in 32 bits. In contrast, given any fixed number of bits, most calculations with real numbers will produce quantities that cannot be exactly represented using that many bits. Therefore the result of a floating-point calculation must often be rounded in order to fit back into its finite representation. This rounding error is the characteristic feature of floating-point computation.



回答2:

Double precision is not exact, so internally 33.46639 is actually stored as 33.466389

Edit: As Richard said, it's floating point data, (stored in binary in a finite set of bits) so it's not exactly that) ....



回答3:

It was New Years' Eve at the end of 1994. Andy Grove, CEO of Intel, was coming off a great year, what with the Pentium processor coming out and being a big hit. So, he walked into a bar and ordered a double shot of Johnnie Walker Green Label.

The bartender served it up and said, "that will be $20, sir."

Grove put a twenty dollar bill on the counter, looked at it for a moment, and said, "keep the change."

http://en.wikipedia.org/wiki/Pentium_FDIV_bug



回答4:

The reason is that 33.46639 will be represented as something slightly less than that number.

Multiplying by 1000000 will give you 33466389.99999999.

Type-casting using (int) will then just return the integer part (33466389).

If you want the "right" number, try round() before type casting.



回答5:

If you're asking why it doesn't become 33466390, it's because doubles do not have infinite precision, and the number cannot be expressed exactly in binary.

If you replace the double with a decimal ((int)(33.46639m * 1000000)), it be equal to 33466390, because decimals are calculated in base 10.



回答6:

Because 33.46639 can't be expressed exactly in a finite number of binary digits. The actual result of 33.46639 * 1000000 is 33466389.9999999962747097015380859375. The cast truncates it to 33466389.



回答7:

The reason you got a different result is the fact that you used a 'cast'

(int)(33.46639 * 1000000) returns 33466389
^^^^^

to cast the result to a type of 'int'... which either rounded up or down the integral type when multipled together and then converted to 'int'.... do not rely on floating point to be accurate enough....Skeet posted an excellent introduction on his site here and here...