Convert.ToDouble(对象)中的小数精度是否依赖于文化?

时间:2012-09-13 14:55:41

标签: c# precision currentculture

可能这是一个非常基本的问题,但我真的很想知道究竟发生了什么。

例如,如果我们在c#中执行以下操作:

object obj = "330.1500249000119";
var val = Convert.ToDouble(obj);

val成为:330.15002490001189

问题是为什么最后9个被89替换?我们可以阻止它以这种方式发生吗?这精确度取决于当前的文化吗?

4 个答案:

答案 0 :(得分:4)

这与文化无关。有些数字不能用base-2数字来表示,就像在base-10中一样,1/3不能用.3333333完全表示

请注意,在您的特定情况下,您输入的数字比数据类型允许的数字更多:Double的有效数字是15-16(取决于范围),您的数字超出了这个数字。

在这种情况下,您可以使用Double代替Decimal

object obj = "330.1500249000119";
var val = Convert.ToDecimal(obj);

答案 1 :(得分:2)

decimal会保留精确度。

object obj = "330.1500249000119";
var val = Convert.ToDecimal(obj);

您遇到的“问题”是浮点表示。

http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

答案 2 :(得分:0)

不,你不能阻止它发生。您正在解析具有数据类型可以表示的更多数字的值。

精确度不依赖于文化。 double始终具有相同的精度。

所以,如果你不想让它发生,那就干脆不去做。如果您不想要浮点数限制精度的影响,请不要使用浮点数。如果您使用固定点数(十进制),它可以准确地表示该值。

答案 3 :(得分:-1)

CPU表示8个字节的双精度数。其分为1个符号位,11个指针用于指数(“范围”),52个用于尾数(“精度”)。 你的范围和精度都有限。

<float.h>中的C常量 DBL_DIG 告诉您,这样的双精度数字只能精确地表示 15位,而不是更多。但是这个数字完全取决于你的c库和CPU。

330.1500249000119包含18位数字,因此将四舍五入为330.150024900012。 330.15002490001189只有一个,这很好。通常你应该期望1.189对1.2。

对于背后的确切数学,尝试阅读David Goldberg,“每个计算机科学家应该知道的关于浮点算术的内容”,ACM Computing Surveys 23,1(1991-03),5-48。如果您对细节感兴趣,这是值得一读的,但它确实需要计算机科学的背景。 http://www.validlab.com/goldberg/paper.pdf

你可以通过使用更好的浮点类型来阻止这种情况发生,例如long double或__float128,或者使用更好的cpu,比如Sparc64或s390,它们在HW中本身使用41位数字(__float128)作为long double。

是的,使用UltraSparc / Niagara或IBM S390就是文化。

通常的答案是:使用 long double ,老兄。这为英特尔(18位)增加了两个字节,还有几个powerpc(31位),sparc64 / s390为41。