ToString中的.NET舍入错误("f2")

Fil*_*unc 6 c# c++ rounding-error

你好,我在C#中有这个代码:

float n = 2.99499989f;
MessageBox.Show("n = " + n.ToString("f2", CultureInfo.InvariantCulture));
Run Code Online (Sandbox Code Playgroud)

而这个C++代码:

float n = 2.99499989f;
printf("n = %.2f", n);
Run Code Online (Sandbox Code Playgroud)

一个输出3.00.
第二个输出2.99.

我不知道为什么会这样.

更新:

我也尝试了Objective-C NSLog,输出为2.99.

我需要快速修复它,所以我使用以下方法:

float n = 2.99499989f;
float round = (float)Math.Round(n, 2);
MessageBox.Show("round = " + round.ToString(CultureInfo.InvariantCulture));
Run Code Online (Sandbox Code Playgroud)

此代码显示2.99,但以双精度计算舍入.我找不到Math.RoundF.

Aak*_*shM 6

使用BitConverter.GetBytes和打印出产生的实际字节表明,这是不是一个编译器的区别-在这两种情况下,存储的实际浮动值0x403FAE14,其中这个方便的计算器告诉我是确切数值

2.99499988555908203125
Run Code Online (Sandbox Code Playgroud)

因此,必须区别在于不同的行为printfToString.不止于此我无法立即说出来.


Maf*_*osh 2

(我意识到这是一个老问题,但我回答这个问题是因为我自己理解了一些事情......)

我的建议是“printf”在应用格式之前将浮点数转换为双精度数。我尝试将浮点数转换为双精度数,然后查看双精度数的 ToString("f2") 结果,它在与浮点数的值四舍五入相反的方向上进行舍入。

其他人强化了关于 printf 的这个想法:

C 自动将浮点值转换为双精度值(这是调用采用变量参数的函数(例如 int printf...)时进行的标准转换。

/sf/answers/523617111/

/sf/answers/447702321/

我相信浮点向上舍入的原因是因为 2.995F 不能完美转换为二进制并且 = 2.99499989F,并且我们期望 2.995 向上舍入。

我相信将浮点数复制到双精度数向下舍入的原因是因为 2.995 作为双精度 <> 2.99499989 作为双精度,并且 2.995 实际双精度值大于该值(更精确更接近其真实的十进制值),因此该值我们预计会向下舍入。

尽管 2.99499989F 看起来小于 2.995,但它四舍五入到 3.00 似乎是错误的,但请记住,2.99499989 是小数,而不是浮点数,并且您将其“转换”为浮点数,基本上是将基数转换为10 到以 2 为基数,实际上是 1 和 0,然后要求它以 10 为基数进行四舍五入,这意味着必须进行转换。嗯,我提到的至少有 2 个以 10 为基数的值可以转换为浮点数,其中最简单的是 2.995。