将浮点数转换为双精度数

12

我正在尝试将Single转换为Double,同时保留原始值。我找到了以下方法:

Single f = 5.2F;
Double d1 = f; // 5.19999980926514
Double d2 = Double.Parse(f.ToString()); // 5.2 (correct)

这种做法值得推荐吗?我不需要最优的方法,但是预期的数值必须传递到double中。在将一个四舍五入的值存储到double中是否会有后果呢?


1
并非所有浮点数都能被准确表示,这就是为什么5.2会变成5.19999980926514的原因。 - npinti
1
从二进制的角度来看,是这样的。5.2不能被表示为一个二进制浮点数,所以它会给出它所能表示的最接近的值。 - D Stanley
我理解,但字符串转换是一个大胆的举动,它是不可避免的吗? - toplel32
2
你对那些数字在做什么?是的,将单精度浮点数转换为字符串再解析为双精度浮点数可能不是最佳方法。 - D Stanley
1
@DStanley - 最好是硬编码,但我不能假设。浮点逻辑是我的绝对弱点;我真正需要知道的是如何在保持可表示性的情况下将Single转换为Double,因为这些值在某个时候被序列化了。我认为我理解直接将Single转换为Double不会有害,但这是一个表现问题。 - toplel32
显示剩余6条评论
3个回答

15

你可以使用 "decimal" 代替字符串。

float f = 5.2F;
decimal dec = new decimal(f);//5.2
double d = (double)dec; //5.2

8
转换是精确的。所有的 Single 值都可以用一个 Double 值来表示,因为它们是用相同的方式“构建”的,只是具有更多可能的数字。你看到的 5.2F 实际上是 5.1999998092651368。如果你访问http://www.h-schmidt.net/FloatConverter/IEEE754.html,并插入 5.2,你将看到它具有 2^2(即 4)的指数和 1.2999999523162842 的尾数。现在,如果你将这两个数相乘,你将得到 5.1999998092651368Single 的最大精度为7 位数,所以.NET 只显示 7 位数。稍微四舍五入一下,5.1999998092651368 就是 5.2

2
5.1999998092651368本身就是一个四舍五入的值。它不能被准确地表示为二进制分数。最接近5.2的浮点数是5.19999980926513671875。最接近5.2的双精度浮点数是5.20000000000000017763568394002504646778106689453125。 - Patricia Shanahan

0
如果您知道您的数字是例如0.01的倍数,我建议您转换为double类型,四舍五入到最近的整数,并减去它以获得小数余数。将其乘以100,四舍五入到最近的整数,然后除以100。将其加到整数部分以获得最接近原始数字的0.01倍数的double表示形式。
请注意,根据float值的来源不同,这种处理可能会或可能不会提高准确性。最接近9000.02的float值约为9000.019531,最接近9000.021的float值约为9000.021484f。如果这些值是通过将9000.020和9000.021转换为float得到的,则它们之间的差异应该约为0.01。然而,如果它们是通过计算9000f+0.019531f9000f+0.021484f等方式得到的,则它们之间的差异应该更接近0.02。在做减法之前四舍五入到最近的0.01会提高前一种情况下的准确性,但会降低后一种情况下的准确性。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接