2010-03-11 94 views
18

(int)(33.46639 * 1000000)返回33466389为什么(int)(33.46639 * 1000000)返回33466389?

为什么会发生这种情况?

+0

你期望发生的? – SLaks 2010-03-11 01:54:26

+0

@Slaks:3346639,又名,正确的答案。 – 2010-03-11 01:56:04

+0

开始的好地方:http://docs.sun.com/source/806-3568/ncg_goldberg.html(每个计算机科学家应该了解浮点运算) – mjv 2010-03-11 01:57:04

回答

31

浮点数学并不完美。 What every programmer should know关于它。

浮点运算被许多人认为是一个深奥的主题。这是相当令人惊讶的,因为浮点在计算机系统中无处不在。几乎每种语言都有一个浮点数据类型;从PC到超级计算机的计算机都有浮点加速器;大多数编译器会被要求不时地编译浮点算法;几乎每个操作系统都必须响应浮点异常,例如溢出。本文提供了一个关于浮点的方面的教程,这些方面对计算机系统的设计者有直接的影响。它从浮点表示和舍入错误的背景开始,继续讨论IEEE浮点标准,并结合大量计算机构建者如何更好地支持浮点的例子。

...

挤压无穷多的实数为有限位数需要一个近似表示。虽然有无限多的整数,但在大多数程序中,整数计算的结果可以存储在32位中。相反,给定任意固定的位数,大多数使用实数的计算都会产生无法使用多位来精确表示的数量。因此,浮点计算的结果必须经过四舍五入以适应其有限表示。该舍入误差是浮点计算的特征。

+1

的确,浮点运算既无处不在,也很复杂,但这并不能回答这个问题(除非您链接到一个有答案的80页的论文)。 – 2010-03-11 02:00:45

+2

@亨利 - 重点在于链接文章的标题。 **每个**程序员都应该知道这一点,如果他们不这样做,他们应该阅读文章。 (好吧,也许不是所有的80页...) – 2010-03-11 02:16:36

+9

+1:链接到一个80页的文件,有答案的地方是标准anwser。这个问题 - 以某种形式 - 被频繁地询问。本文是*答案。问题都是重复的。我们不需要一再重复这些信息。 – 2010-03-11 02:25:56

5

双精度不准确,所以在内部33.46639实际存储为33.466389

编辑:正如理查德说,它的浮点数据(以二进制存储在一个有限的位集合),所以它不完全是) ...

+1

或33.4668885或其他“足够接近”,取决于硬件。 – DaveE 2010-03-11 01:57:19

+1

嗯,以上都不是。它的基数为2.大多数这样的数字不能完全以10为底数表示(不管怎样,无需使用无限重复的数字序列,类似于基数10中的1/3必须表示为0.33333 [inf]。) – 2010-03-11 02:02:37

+0

,不完全是......但比原来的更接近那个。 – 2010-03-11 02:06:11

-1

你有不同的结果的原因是,您使用的“

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

的结果转换为一个类型的“廉政”的事实......这无论是围捕或向下整数类型时,一起倍增,然后转换为'int'....不要依靠浮点足够准确.... Skeet张贴在他的网站上的优秀介绍herehere ...

+0

演员阵容本身没有任何损失。存在任意精度库。 – 2010-03-11 01:57:59

+0

我想象他在问:“我的结果中有8个来自哪里?”乘以1000000就像将小数点6位移到右边,应该是“33466390”,但这不是他所得到的。你的答案是我最初想的,直到我再次读到这个问题。 – Pwninstein 2010-03-11 01:59:48

+0

@Richard - 将'float'或'double'强制转换为'int'会丢弃小数部分,所以您确实会丢失信息。 – Seth 2010-03-11 02:32:50

1

如果你问它为什么没有变成33466390,这是因为doubles没有无限精度,而且数字不能用二进制精确表示。

如果更换doubledecimal(int)(33.46639m * 1000000)),它等于33466390,因为decimal s的在碱计算10.

+0

像这些问题是浮点内在的问题,而不仅仅是二进制浮点。当然,十进制得到了33.46639 * 1000000的权利,但仍然有1/3 * 3!= 1和pow(sqrt(2),2)!= 2. – dan04 2010-03-11 02:33:12

+0

是的,但他的具体问题是由于二进制。 – SLaks 2010-03-11 02:40:59

2

其原因是33.46639将被表示为一些比该数量稍少。

乘以1000000会给你33466389.99999999。

使用(int)进行类型转换将仅返回整数部分(33466389)。

如果您想要“正确”的数字,请在类型转换之前尝试round()。

+4

哇! .....不不,不,不。如果你想要“正确的”答案,你不能使用浮点运算。 – 2010-03-11 02:08:40

+4

不可以。如果你想要“正确”的答案,你不能使用*二进制*浮点运算。使用使用十进制浮点运算的“decimal”类型,它将按照您的预期工作。 – Gabe 2010-03-11 02:13:58

+1

33.46639是“正确的”答案。问题是提问者没有提出正确的问题。 – 2010-03-11 02:21:54

1

因为33.46639不能准确地表示有限数量的二进制数字。 33.46639 * 1000000的实际结果是33466389.9999999962747097015380859375。演员将它截断为33466389.

+0

尝试“不能准确表达在有限数量的小数二进制数字” – 2010-03-11 07:15:42

3

这是1994年底的除夕夜。英特尔首席执行官安迪格罗夫(Andy Grove)出现了一个伟大的一年,奔腾处理器出现并受到重创。于是,他走进一家酒吧,点了一瓶Johnnie Walker绿色标签。

酒保送达并说,“那将是20美元,先生。”

格罗夫在柜台上放了一张二十美元的钞票,看了一会儿,说道:“保持变化。”

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

+0

但是...这是一个整数... – Rawling 2014-06-11 08:37:00

相关问题