.net 如何实现单精度到双精度的转换

.net 如何实现单精度到双精度的转换,.net,floating-point,.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 这完全出乎意料。为什么会发生这种情况?我如何解决 预计到达时间: 这不是我的代码,原来的输入是以字符串“1.15”的形式输入的,所以他们将其转换为单精度,然后是双精度。删除单个部分使每个人都感到高兴。在计算机

这个小小的代码简介

    Dim s As Single = 1.15
    Dim d As Double = CDbl(s)
    Console.WriteLine(s)
    Console.WriteLine(d)
收益率:

1.15
1.14999997615814
这完全出乎意料。为什么会发生这种情况?我如何解决

预计到达时间:


这不是我的代码,原来的输入是以字符串“1.15”的形式输入的,所以他们将其转换为单精度,然后是双精度。删除单个部分使每个人都感到高兴。

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

如果查看这两个值的基2表示形式,您会发现它们相距不远

小数点1.15的二进制值为1.00100110011001…无穷大。使用
单个
得到23位尾数,使用
得到52位尾数。显然,以有限的精度,尾数的重复将在不同的地方被切断


如果您希望数字以相同的10为基数显示,则必须使用一点斜率,除非您通知字符串转换例程以更好的方式对其进行格式化。

尽管
s
d
包含完全相同的数值,由于将
单数
双数
转换为文本时使用的位数不同,因此会为它们显示不同的数字

Console.WriteLine
调用
Console.WriteLine(Single)
,它使用
Single.ToString
生成
s
的文本表示形式,并使用文档中的格式说明符“G”进行转换。类似地,
Console.Writeline(d)
调用
Double.ToString

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

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

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

因此,将
单次
转换为
双次
时没有错误。这只是一种展示的错觉


请注意,
Double
转换为
Single
时通常会出现错误。如果您将
Dim d写成Double=1.15
,那么
d
将被设置为1.149999999999111821580987476766109466552734375,我希望
控制台。WriteLine(d)
将产生“1.15”。将
d
转换为
Single
将产生1.14999979615814208984375。

二进制浮点系统不容易满足工程术语中的十进制“精度”。也许你的意思是显示四舍五入?你所看到的“不精确”完全在你的脑海中。如果你需要非整数数学的精确性,那么最好使用十进制类型。或者使用有理数类型。或者知道需要保留多少sig数字,并在计算之后,在更改类型之前,始终四舍五入到该数字。顺便说一句,这里是C版本。这个答案无法解释为什么相同的数值打印方式不同。@EricPostChil:如果你认为这个答案令人困惑,我可以补充更多细节。然而,给出的信息足够了。当分配给
单个
时,“1.15”的四舍五入方式会有所不同,因为它们的有效位长度不同,这一事实并不是问题的原因,并且这个答案不正确,表明它是。在这个问题中,
s
d
的数值是完全相同的,因为
d
被分配了
Dim d作为Double=CDbl(s)
,因此它在已经被四舍五入到较短的
单个有效位后收到了值。此外,
Single
Double
的有效位分别为24位和53位。它们部分用23位和52位字段编码,但有效位包括从指数字段派生的附加位。(“有效位”是首选术语;有效位是线性的,但尾数是对数的。)