将浮点转换为双精度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