如何从单一转换为双精度并保持精度

时间:2013-05-23 15:14:14

标签: .net floating-point

这个小代码模糊

    Dim s As Single = 1.15
    Dim d As Double = CDbl(s)
    Console.WriteLine(s)
    Console.WriteLine(d)

的产率:

1.15
1.14999997615814

这是完全出乎意料的。为什么会发生这种情况?我该如何解决这个问题?

ETA:

这不是我的代码,事实证明原始输入是以字符串“1.15”形式出现的,所以他们将它转换为单个,然后加倍。删除单个部分让每个人都高兴。

2 个答案:

答案 0 :(得分:1)

在计算机科学的语言中,精确度是根据尾数和指数的大小给出的。它与“重要人物”无关。也许最令人困惑的是,您正在基数10 中查看 base 2 浮点数!

如果您查看这两个值的基数2表示,您会发现它们相差不远。

十进制1.15的二进制值为1.00100110011001 ... ad infinitum 。你得到23位尾数Single和52位尾数Double。显然,在精确度有限的情况下,尾数中的重复将在不同的地方被切断。

如果您希望以相同的基数10表示显示数字,除非您通知字符串转换例程以更好的方式格式化它,否则您将不得不忍受一些slop。

答案 1 :(得分:1)

虽然sd包含完全相同的数值,但会为它们显示不同的数字,因为SingleDouble转换为文本的位数不同

Console.WriteLine(s)调用Console.WriteLine(Single),使用s生成Single.ToString的文本表示,并使用格式说明符“G”进行转换,文本说明符here。同样,Console.Writeline(d)会调用Double.ToString

根据文档,Single使用的最大位数为7,Double为15。我没有看到指定实际使用位数的文档,只是最大值。

语句Dim s As Single = 1.15s设置为值1.14999997615814208984375,因为这是最接近1.15的Single值。 (第二个最接近的是1.150000095367431640625。)当您将该值四舍五入为七位小数时,结果为“1.150000”。我假设.NET省略了尾随的零,产生“1.15”。

d设置为相同值并打印时,使用15位数字。当1.14999997615814208984375四舍五入为15位时,结果为“1.14999997615814”。

因此,Single转换为Double时没有错误。这只是一种展示的幻觉。

请注意,Double转换为Single时通常会出错。如果你写了Dim d As Double = 1.15,那么d将被设置为1.149999999999999911182158029987476766109466552734375,我希望Console.WriteLine(d)会产生“1.15”。将d转换为Single会产生1.14999997615814208984375。

相关问题