C# c更精确地打印浮点值

C# c更精确地打印浮点值,c#,C#,我希望打印精度高于默认值的浮动 例如,当我从浮点打印PI值时,我得到6个小数。但是如果我把同一个值从浮点复制成一个双精度,然后打印出来,我得到14位小数 为什么我在打印相同的值时会获得更高的精度 如何使Console.WriteLine在打印浮点时输出更多的小数,而无需先将其复制到双精度中 我也尝试了0.0000000000,但它没有写得更精确,只是增加了更多的零-/ 我的测试代码: float x = (float)Math.PI; double xx = x; Console.WriteLi

我希望打印精度高于默认值的浮动

例如,当我从浮点打印PI值时,我得到6个小数。但是如果我把同一个值从浮点复制成一个双精度,然后打印出来,我得到14位小数

为什么我在打印相同的值时会获得更高的精度

如何使Console.WriteLine在打印浮点时输出更多的小数,而无需先将其复制到双精度中

我也尝试了0.0000000000,但它没有写得更精确,只是增加了更多的零-/

我的测试代码:

float x = (float)Math.PI;
double xx = x;
Console.WriteLine(x);
Console.WriteLine(xx);

Console.WriteLine($"{x,18:0.0000000000}"); // Try to force more precision 
Console.WriteLine($"{xx,18:0.0000000000}");
输出:

3,141593
3,14159274101257
      3,1415930000  <-- The program just added more zeroes :-(
      3,1415927410
我还试着在

PI的二进制浮点表示为0B010000001010010000111111011011011

因此,该值为:2*0b1.1001001000011111011=2*1.570796370506286622109375=3.1415927410125732421875


所以要输出更多的小数。如何让C输出整个值?

C中的浮点精度为7位,不超过7位。这意味着小数点前1位,小数点后6位

如果输出中还有更多的数字,那么它们可能是完全错误的

如果需要更多的数字,则必须使用精度为15-16位的双精度或精度为28-29位的十进制


您可以很容易地验证,因为PI的数字与您的输出略有不同。正确的前40位是:3.14159 26535 89793 23846 26433 83279 50288 4197

c中的浮点精度为7位,不超过7位。这意味着小数点前1位,小数点后6位

如果输出中还有更多的数字,那么它们可能是完全错误的

如果需要更多的数字,则必须使用精度为15-16位的双精度或精度为28-29位的十进制


您可以很容易地验证,因为PI的数字与您的输出略有不同。正确的前40位数字是:3.14159 26535 89793 23846 26433 83279 50288 4197

浮点中没有更高的精度。当你把它转换成双精度的时候,精度就更差了,即使数字的精度增加了-基本上,你在双精度打印中看到的所有额外数字都是转换伪影-它们是错误的,只是你在双精度打印中可以得到的给定浮点数的最佳表示。这与二进制浮点数的工作方式有关

让我们看看浮点的二进制表示:

01000000010010010000111111011100
第一位是符号,接下来的八位是指数,其余的是尾数。当我们把它投给替补时会得到什么?指数保持不变,但尾数用零填充。但这实际上改变了这个数字——你得到了3.1415929794311523四舍五入,就像使用二进制浮点数一样,而不是正确的3.14159265358979π的双精度值。你得到了更高精度的错觉,但这只是一种错觉——数字不再比以前精确,你只是用噪声代替了零

浮动和双精度之间没有1:1的映射。相同的浮点值可以由许多不同的双精度值表示,数字的十进制表示形式可以相应地改变。如果您关心十进制精度,则每次将float转换为double后都应该执行舍入操作。请考虑这个代码:

double.Parse(((float)Math.PI).ToString())
我没有将float转换为double,而是首先将其更改为字符串中的十进制表示形式,并由此创建了double。现在,不再使用截断的双精度,而是使用了一个正确的双精度,它不需要额外的精度;当你打印出来的时候,你会得到3.1415930000。当然,仍然是四舍五入,因为它仍然是二进制->十进制转换,但不再假装比实际精度更高-四舍五入发生在比浮点版本更晚的数字上,零实际上是零,除了最后一个近似为零


如果需要实际十进制精度,则可能需要使用十进制类型,例如int或decimal。float和double都是二进制数,只有二进制精度。有限的十进制数在二进制中不一定是有限的,就像有限的三进制数在十进制中不一定是有限的,例如1/3没有有限的十进制表示。

浮点中没有更高的精度。当你把它转换成双精度的时候,精度就更差了,即使数字的精度增加了-基本上,你在双精度打印中看到的所有额外数字都是转换伪影-它们是错误的,只是你在双精度打印中可以得到的给定浮点数的最佳表示。这与二进制浮点数的工作方式有关

让我们看看浮点的二进制表示:

01000000010010010000111111011100
第一位是符号,接下来的八位是指数,其余的是尾数。当我们把它投给替补时会得到什么?指数保持不变,但尾数用零填充。但这实际上改变了数字-你 像往常一样,使用二进制浮点而不是正确的3.14159265358979 pi双精度值,获得3.1415929794311523四舍五入。你得到了更高精度的错觉,但这只是一种错觉——数字不再比以前精确,你只是用噪声代替了零

浮动和双精度之间没有1:1的映射。相同的浮点值可以由许多不同的双精度值表示,数字的十进制表示形式可以相应地改变。如果您关心十进制精度,则每次将float转换为double后都应该执行舍入操作。请考虑这个代码:

double.Parse(((float)Math.PI).ToString())
我没有将float转换为double,而是首先将其更改为字符串中的十进制表示形式,并由此创建了double。现在,不再使用截断的双精度,而是使用了一个正确的双精度,它不需要额外的精度;当你打印出来的时候,你会得到3.1415930000。当然,仍然是四舍五入,因为它仍然是二进制->十进制转换,但不再假装比实际精度更高-四舍五入发生在比浮点版本更晚的数字上,零实际上是零,除了最后一个近似为零


如果需要实际十进制精度,则可能需要使用十进制类型,例如int或decimal。float和double都是二进制数,只有二进制精度。有限的十进制数在二进制中不一定是有限的,就像有限的三进制数在十进制中不一定是有限的一样,例如,1/3没有有限的十进制表示。

以十进制后6位打印值

Console.WriteLine("{0:N6}", (double)2/3);
输出:

0.666667

打印小数点后6位的值

Console.WriteLine("{0:N6}", (double)2/3);
输出:

0.666667

不,在转换浮点数->双位数的地方发明了。。。与31415927410不同的Math.PI==3.1415926536为什么首先将其转换为float?不能对字符串格式函数施加更高的精度。显示值的方式不会影响其中的内容。float x=floatMath.PI;我只是想为这个论坛做个榜样。在我的程序中,我从一个连接的设备中读取了一组浮点值,现在我将它们输出到一个文本文件中,以供MATLAB读取。正因为如此,我希望保持尽可能高的精度。所有可用的最高精度都显示在Math.PI.ToStringRNo中,在转换浮点->双位数中发明了。。。与31415927410不同的Math.PI==3.1415926536为什么首先将其转换为float?不能对字符串格式函数施加更高的精度。显示值的方式不会影响其中的内容。float x=floatMath.PI;我只是想为这个论坛做个榜样。在我的程序中,我从一个连接的设备中读取了一组浮点值,现在我将它们输出到一个文本文件中,以供MATLAB读取。正因为如此,我希望保持尽可能高的精度。所有可用的最高精度都是用Math.PI.ToStringRfloat to double显示的,应该是无损的,对于任何一个float的double,我认为应该可以执行float->double->floatlossless@xanatos这有点棘手。如果将浮点转换为十进制,将该十进制转换为双精度,然后将双精度转换为十进制,再转换为浮点,那么假设原始浮点也是由十进制创建的,当然不会有任何损失。但铸造更棘手——铸造浮动双浮动不应该失去任何东西,因为你所做的基本上是填充和截断,但中间的任何操作都会把事情搞砸。要表示与双精度浮点值相同的浮点值,强制转换不是正确的操作-您还需要正确地对双精度浮点值进行舍入。@xanatos,但我同意这比不舍入更令人困惑,所以我将重写一点。是的,我的意思正是floatdouble0。1234f@xanatos是的,应该没问题。虽然我必须指出,用于浮点数学的数字不一定是单精度和双精度的,它们也可能是不同精度的浮点二进制数。我不确定这是否会在某些奇怪的情况下或边缘值导致转换损失。浮点到双精度应该是无损的,对于任何双精度浮点,我认为应该可以执行浮点->双精度->浮点lossless@xanatos这有点棘手。如果将浮点转换为十进制,将该十进制转换为双精度,然后将双精度转换为十进制,再转换为浮点,那么假设原始浮点也是由十进制创建的,当然不会有任何损失。但铸造更棘手——铸造浮动双浮动不应该失去任何东西,因为你所做的基本上是填充和截断,但中间的任何操作都会把事情搞砸。要表示与双精度浮点值相同的浮点值,强制转换不是正确的操作-您还需要正确地对双精度进行舍入。@xanatos,但我同意这比不舍入更容易混淆,因此我将重写它
是的,我的意思是0。1234f@xanatos是的,应该没问题。虽然我必须指出,用于浮点数学的数字不一定是单精度和双精度的,它们也可能是不同精度的浮点二进制数。我不确定在某些奇怪的条件或边缘值下,这是否会导致转换损失。