将浮点转换为双精度C#
我有以下代码将浮点转换为双精度C#,c#,types,casting,floating-point,C#,Types,Casting,Floating Point,我有以下代码 double temp3 = 61.01; //This can actually be various other types, but float is the one that causes problems dynamic temp = 61.01f; double temp2 = (double)Convert.ChangeType(temp, typeof(double)); double newValue = temp2 -
double temp3 = 61.01;
//This can actually be various other types, but float is the one that causes problems
dynamic temp = 61.01f;
double temp2 = (double)Convert.ChangeType(temp, typeof(double));
double newValue = temp2 - temp3;
//newValue should == 0 but it does not
Console.WriteLine(String.Format(" {0:F20}", temp));
Console.WriteLine(String.Format(" {0:F20}", temp2));
Console.WriteLine(String.Format(" {0:F20}", temp3));
Console.WriteLine(String.Format(" {0:F20}", newValue));
产生
6101000000000000000000
61.00999832153320000000
6101000000000000000000
-0.0000016746679488548
为什么Convert.ChangeType会丢失精度
我们之所以使用Convert.ChangeType,是因为使用了一个动态变量,它可以是byte/uint/float/double等。这是因为float分配给它们的比特量比double小。浮点数通常有23位,而双精度浮点数有52位。因此,通过转换,基本上就是切掉位,直到可以将其放入浮点。因此,这就是您降低精度的原因。此问题中观察到的问题主要是由Microsoft选择的格式造成的,尤其是Microsoft软件无法显示准确的值,因为它限制了用于转换为十进制的位数,即使格式字符串要求更多位数。此外,转换
浮点
时使用的数字比转换双精度
时更少。因此,如果格式化具有相同值的float
和double
,结果可能不同,因为float
格式化将使用较少的有效数字
下面,我逐一浏览问题中的代码语句。总之,问题的关键在于,当值61.0099983215332是浮点时,它的格式为“61.0100000000000”;当值是双精度时,它的格式为“61.0099983215332”。这纯粹是微软对格式的选择,而不是由浮点运算的性质造成的
语句double temp3=61.01
将temp3
初始化为61.00999999999980104010480339871947956085205078125。由于二进制浮点格式的性质,它不能精确表示61.01,因此需要对61.01进行此更改,因此使用了可在double
中表示的最近值
语句dynamic temp=61.01f
将temp
初始化为61.009998321533203125。与double
一样,使用了最接近的可表示值,但由于float
精度较低,因此最接近的值不如double
情况下的值接近
语句double temp2=(double)Convert.ChangeType(temp,typeof(double))代码>将temp
转换为与temp
具有相同值的double
,因此其值为61.009998321533203125
语句double newValue=temp2-temp3代码>正确减去这两个值,生成准确的结果0.00000167466794885480339871947956085205078125,无错误
语句Console.WriteLine(String.Format(“{0:F20}”,temp))代码>格式化名为temp
的浮点值。格式化float
涉及调用。微软的文档有点模糊。它表示,默认情况下,只返回七位(十进制)精度。它说使用G
或R
格式最多可以得到九种格式,F20
既不使用G
也不使用R
。所以我相信只使用了七位数字。当61.009998321533203125四舍五入到七位有效十进制数字时,结果为“61.01000”。然后,ToString
方法将其填充到小数点后20位,生成“61.01000000000000000000”
接下来,我将介绍您的第三个WriteLine
语句,然后再回到第二个
语句Console.WriteLine(String.Format(“{0:F20}”,temp3))
格式化名为temp3
的double
。由于temp3
是一个double
,因此调用。此方法使用15位精度(除非使用G
或R
)。如果将61.009999999980100480339871947956085205078125四舍五入为15位有效十进制数字,则结果为“61.0100000000000”。然后,ToString
方法将其填充到小数点后20位,生成“61.01000000000000000000”
语句Console.WriteLine(String.Format(“{0:F20}”,temp2))
格式化名为temp2
的double
temp2
是一个double
,它包含来自float
temp
的值,因此它包含61.009998321533203125。将其转换为15位有效十进制数字时,结果为“61.0099983215332”。然后,ToString
方法将其填充到小数点后20位,生成“61.0099983215332000000”
最后,语句Console.WriteLine(String.Format(“{0:F20}”,newValue))代码>格式newValue
。将.00000 16784667948854803398771947956085205078125格式化为15个有效数字将生成“0.00000 167846679488548”。我相当确定答案仍然与相同。您的源数据类型是float
,并且.01
无法用二进制准确表示:111101.000000 10100011101
()。顺便说一下,请将格式更改为G20
,而不是F20
。我现在明白了。F20是我的问题,通过使用G20,我可以看到真实值。@约翰:除了源文本的格式和转换之外,这个问题中似乎没有任何浮点算术错误。这个问题似乎是微软格式的问题,而不是浮点的问题。请不要随意将浮点数问题作为的重复项关闭,因为这会妨碍人们获得正确答案。@LasseVågsætherKarlsen:除了源文本的格式和转换之外,此问题中似乎没有任何浮点数算术错误。这个问题似乎是微软格式的问题,而不是浮点的问题。请不要随意关闭浮点q