.net C语言中的双精度魔术#

.net C语言中的双精度魔术#,.net,.net,这是一个非常简单的例子来演示浮点不精确性: double a = 0.33; double b = 0.1; double c = a + b; printf("%.90f\n", c); // output: 0.430000000000000048849813083506887778639793395996093750000000000000000000000000000000000000 C#中的相同代码似乎会产生“C”的精确值: double a = 0.33;

这是一个非常简单的例子来演示浮点不精确性:

double a = 0.33;
double b = 0.1;
double c = a + b;

printf("%.90f\n", c);

// output: 0.430000000000000048849813083506887778639793395996093750000000000000000000000000000000000000
C#中的相同代码似乎会产生“C”的精确值:

double a = 0.33;
double b = 0.1; 
double c = a + b;

Console.WriteLine($"{c:N90}");
  
// output: 0.430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

在C#/dotNet端发生了什么?

以下是我在VS2019中使用的代码

static class Program
{
    static void Main(string[] args)
    {
        double a = 0.33;
        double b = 0.1;
        double c = a + b;

        Console.WriteLine($"{"Format",-8} {"Value"}");

        Console.WriteLine($"{"G",-8} {c:G}");
        Console.WriteLine($"{"R",-8} {c:R}");
        Console.WriteLine($"{"F40",-8} {c:F40}");
        Console.WriteLine($"{"N40",-8} {c:N40}");            
    }
}
与输出

Format   Value
G        0.43
R        0.43000000000000005
F40      0.4300000000000000000000000000000000000000
N40      0.4300000000000000000000000000000000000000
因此,即使存储的位值对应于
0.43000000000000005
,显示过程也会从末尾循环一些位,以使数字更精确

0.43000000000000005 = 0b11111111011011100001010001111010111000010100011110101110000110
0.43000000000000000 = 0b11111111011011100001010001111010111000010100011110101110000101
差值是向下舍入的最后一位。这段逻辑必须隐藏在框架中
double
的格式化函数中


更深入地了解一下,以下情况发生在CLR之外

调用中的以下函数将
双精度
转换为
字符串


如您所见,它被标记为“代码>外部>代码”,这意味着它在基础C++库中调用非托管函数。

我会看到<代码> 0.4300万、48830830530697989697933、960937、3500、000万、000万、000万、000万、000亿,这是代码值>,这是更接近于C++的示例。此外,它的精度为15-17digits@PavelAnikhouski浮动80对浮动64可能?如果在调试版本中尝试,会得到什么结果?Pavel,我从调试器输出窗口复制了结果。您使用的代码与帖子中的代码相同吗?仅供参考-LinqPad5(.Net Framework)给出的代码
0.430000000000000000000000000000000000000000
但LinqPad6(.Net核心)在同一台机器上给出
0.43000000004884981308350688778639793395996093750000000000000000000000000000000000000000000000000000000000000000000
要获得
c
的完整存储值(不舍入最后位),请使用
c.ToString(“R”)