我试图将数字四舍五入到小数点后7位,但我注意到Math.Round在某些数字上无法正常工作:
Math.Round(39.248779999999996,3) => 39.249
Math.Round(39.248779999999996,4) => 39.2488
Math.Round(39.248779999999996,5) => 39.248779999999996
Math.Round(39.248779999999996,6) => 39.248779999999996
Math.Round(39.248779999999996,7) => 39.248779999999996
Run Code Online (Sandbox Code Playgroud)
谁能向我解释这种行为?
如果需要精度,请使用decimal而不是double/ float;
var num = 39.248779999999996; // num is double.
var num = 39.248779999999996m; // num is decimal.
Run Code Online (Sandbox Code Playgroud)
十进制关键字表示128位数据类型。与浮点类型相比,十进制类型具有更高的精度和更小的范围,这使其适用于财务和货币计算。
编辑:
您不能完全以浮点数/双精度数表示所有数字:
只要您知道发生了什么,并且不要期望值恰好是您程序中所输入的十进制值,就可以使用二进制浮点算术,并且不要期望涉及二进制浮点数的计算必然产生精确的结果。即使两个数字都以您使用的类型正确表示,涉及这两个数字的运算结果也不一定会正确表示。用除法最容易看出这一点(例如,尽管1和10都可以精确表示,但1/10不能精确表示),但是任何操作都可能发生这种情况-甚至看似无辜的操作(例如加法和减法)。
例如:
double doubleValue = 1f / 10f; // => 0.10000000149011612
decimal decimalValue = 1m / 10m; // => 0.1
Run Code Online (Sandbox Code Playgroud)
您可以截断数字以确保最多7个数字,但不能精确舍入该值:
double value = 39.248779999999996;
double roundTo = Math.Pow(10, 7);
double resultResult = Math.Truncate(value * roundTo) / roundTo;
// result is : 39.2487799
Run Code Online (Sandbox Code Playgroud)