这个小代码模糊
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”形式出现的,所以他们将它转换为单个,然后加倍。删除单个部分让每个人都高兴。
答案 0 :(得分:1)
在计算机科学的语言中,精确度是根据尾数和指数的大小给出的。它与“重要人物”无关。也许最令人困惑的是,您正在基数10 中查看 base 2 浮点数!
如果您查看这两个值的基数2表示,您会发现它们相差不远。
十进制1.15的二进制值为1.00100110011001 ... ad infinitum 。你得到23位尾数Single
和52位尾数Double
。显然,在精确度有限的情况下,尾数中的重复将在不同的地方被切断。
如果您希望以相同的基数10表示显示数字,除非您通知字符串转换例程以更好的方式格式化它,否则您将不得不忍受一些slop。
答案 1 :(得分:1)
虽然s
和d
包含完全相同的数值,但会为它们显示不同的数字,因为Single
和Double
转换为文本的位数不同
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.15
将s
设置为值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。