C# Math.Round 错误?

C# Math.Round bug?

我试图将数字四舍五入到小数点后 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

任何人都可以向我解释这种行为吗?

如果需要精度,请使用 decimal 而不是 double/float;

var num = 39.248779999999996; // num is double.
var num = 39.248779999999996m; // num is decimal.

The decimal keyword indicates a 128-bit data type. Compared to floating-point types, the decimal type has more precision and a smaller range, which makes it appropriate for financial and monetary calculations.

编辑:

can't 完全代表 float/double:

中的所有数字

Binary floating point arithmetic is fine so long as you know what's going on and don't expect values to be exactly the decimal ones you put in your program, and don't expect calculations involving binary floating point numbers to necessarily yield precise results. Even if two numbers are both exactly represented in the type you're using, the result of an operation involving those two numbers won't necessarily be exactly represented. This is most easily seen with division (eg 1/10 isn't exactly representable despite both 1 and 10 being exactly representable) but it can happen with any operation - even seemingly innocent ones such as addition and subtraction.

例如:

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