2012-02-13 49 views
1

我的应用程序需要执行一些操作:>,<,==,!=,+, - ,++等(但没有除法)。这些数字有时是整数,而更少有浮点数。什么时候双打开始失去精确度?

如果我在内部使用“double”类型(由IEEE 754定义),即使对于整数,直到我可以安全地使用它们,就好像它们是int s一样,没有运行奇怪的舍入错误例如,n == 5 & & n == 6都是真的,因为他们四舍五入到相同的数字)?

很显然,各种操作(+, - 等)的第二个输入始终是一个整数,我知道在0.000 [...] 01之后我会从开始就遇到麻烦。

作为奖励答案,同样的问题,但为float

+3

请选择“c#”或“C++”,因为“double”在这些语言之间执行的并不相同。 – Yuck 2012-02-13 16:32:28

+0

在我脱落之前,我可以走多远到悬崖边缘?当你可以简单地把它们看作整数时,你为什么会冒任何整数的精度损失?什么是想要使用双重的理由? – 2012-02-13 16:33:12

+4

我不认为有可能构建一个例子,在任何情况下'n == 5 && n == 6'都会评估为“true”。 – dasblinkenlight 2012-02-13 16:33:17

回答

0

C#参考: 但是,请注意小数类型的范围小于一倍。这是双倍可以保持更大的价值,但它通过失去精确度。或者,如MSDN上所述:

十进制关键字表示128位 数据类型。与浮点型 类型相比,小数类型具有更高的精度和更小的范围,其中 使其适用于财务计算和 货币计算。下表中显示了 类型的近似 范围和精度。

decimaldouble之间的主要区别是,decimal is fixed-point and double is floating point。这意味着小数存储精确值,而double表示由小数表示的值,并且不太精确。 A decimal是128位,所以需要双倍空间来存储。 decimal的计算也较慢(测量!)。

如果您需要更大的精度,则可以使用.NET 4中的BigInteger。(您需要自己处理小数点)。在这里你应该知道,BigInteger是不可变的,所以对它的任何算术运算都会创建一个新的实例 - 如果数字很大,这可能是性能的缩影。

我建议你看看你需要多少精度。也许你的算法可以使用规范化的值,可以更小?如果性能问题,内置浮点类型中的一种可能会更快。

8

比特在IEEE-754双尾数的数目是52,并且有一个额外的隐含位,始终是1。这意味着可以包含恰好是2^53,或9007199254740992

甲最大值浮点尾数是23位,也是一个隐含位。可精确表示的最大整数是2^24或16777216.

如果您的意图只是保存整数值,通常会有一个64位整数类型,比双精度值更合适。

编辑:最初我有2^53-1和2^24-1,但我意识到没有必要减去1 - 偶数可以利用尾数右边的隐含0位。

+1

'9007199254740992.0 == 9007199254740993.0'的计算结果为true,并且看起来是第一对计算相同数字的整数(在数学意义上)。 – Guvante 2012-02-13 22:20:38

+1

说2^53是“可以包含的最大值”并不完全正确。你真正想要说的是2^53是最大的整数n,使得范围[-n,n]中的每个整数都可以精确地表示为双精度。 – 2012-02-14 15:46:37

+0

@StephenCanon,谢谢澄清。有时候我的语言有点不准确。当然,如果尾数在尾数的右边有零,也可以精确地表示更大的数字,尽管当您尝试使用它时可能会有一些细微的变化。 – 2012-02-14 16:23:13