如果我把0.1赋值给一个float:
float f = 0.1;
存储在内存中的实际值不是0.1的精确表示,因为0.1不是一个可以用单精度浮点格式精确表示的数字。如果我计算正确的话,存储的实际值是
0.100000001490116119384765625
但是我无法确定一种方法来让C#打印出这个值。即使我要求它将数字打印到小数点后许多位,它也不会给予正确答案:
// prints 0.10000000000000000000000000000000000000000000000000
Console.WriteLine(f.ToString("F50"));
如何打印存储在浮点数中的精确值;存储器中位模式实际代表的值?
编辑:在其他地方已经引起了我的注意,你可以使用标准格式字符串得到我要求的行为....NET Core和.NET 5.0所以这个问题是.NET Framework特定的,我猜。
4条答案
按热度按时间u91tlkcl1#
这里的基本思想是将
float
值转换为有理数,然后将有理数转换为小数。下面的代码(提供
BitConverter.SingleToUInt32Bits
方法的.Net 6)将打印float
的确切值(包括NaN
值是否安静/信令、NaN的有效载荷以及是否设置符号位)。请注意,WriteRational
方法 * 不是 * 一般适用于所有有理数,因为它没有尝试检测非终止十进制表示:这在这里不是问题,因为float
中的所有值都具有2的幂分母。我已经用
valueBits
和fractionBits
(在方法的第一行中定义)编写了代码中的大部分常量,以便尽可能简单地将此方法适用于double
。要执行此操作:valueBits
更改为sizeof(double) * 8
fractionBits
更改为52uint
更改为ulong
(包括将1U
转换为1UL
)BitConverter.DoubleToUInt64Bits
而不是BitConverter.SingleToUInt32Bits
让代码具有文化性,留给读者的练习是:-)
gmol16392#
是的,这是C#(或.net)中非常有趣的挑战。恕我直言,最简单的解决方案是将float/double与某个巨大的数字相乘,然后将浮点结果转换为
BigInteger
。例如,这里我们尝试计算1e+51*0.1
的结果:因为浮点格式的0.1只是近似表示,带有机器ε误差。这就是为什么我们得到这个奇怪的结果而不是100...(50个零)。
qnyhuwrf3#
这个答案与C有关,而不是C#。
留下它,因为它可能提供C#洞察力,因为语言在这方面有相似之处。
如何打印存储在浮点数中的精确值?
要打印
float
的十进制值,并具有与所有其他float
不同的小数位数:要打印小数位数的值是很困难的-而且很少需要。代码可以使用更高的精度。经过某个点(例如20位有效数字),则
big_value
可能会丢失低位数的正确性,而printf()
。在C和IEEE 754中允许这种错误:要以十进制形式打印所有
float
的所有小数位数,请编写一个辅助函数。Example。kninwzqo4#
对于.NET Framework,请使用格式字符串
G
。不完全是,但足以解决浮点错误。投票否决...好吧,我找到了dmath, a math library。