我正在尝试将数字舍入到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
有人能解释一下这种行为吗?
答案 0 :(得分:4)
如果您需要精确度,请使用decimal
而非double
/ float
;
var num = 39.248779999999996; // num is double.
var num = 39.248779999999996m; // num is decimal.
decimal关键字表示128位数据类型。相比 浮点类型,十进制类型具有更高的精度和a 较小的范围,这使其适合金融和货币 计算
修改强>
你can't完全代表float / double中的所有数字:
二进制浮点运算只要你知道是什么就可以了 继续,不要指望值正好是十进制的 放入你的程序,不要指望涉及二进制的计算 浮点数必然产生精确的结果。即使 两个数字都在你正在使用的类型中精确表示, 涉及这两个数字的操作的结果不一定 完全代表。这是最容易看到的分裂(例如 尽管1和10都是完全正确的,但是1/10并不完全可以表示 可以表示但是它可以在任何操作中发生 - 甚至看似 无辜的,如加法和减法。
例如:
double doubleValue = 1f / 10f; // => 0.10000000149011612
decimal decimalValue = 1m / 10m; // => 0.1
您可以截断数字以确保最多7位数,但您无法完全舍入该值:
double value = 39.248779999999996;
double roundTo = Math.Pow(10, 7);
double resultResult = Math.Truncate(value * roundTo) / roundTo;
// result is : 39.2487799