C# error casting from double to int32
using NUF = NUnit.Framework;
[NUF.Test]public void DifferentCastingTest() {
NUF.Assert.That((int)0.499999D, NUF.Is.EqualTo(0));
NUF.Assert.That((int)0.500000D, NUF.Is.EqualTo(0)); // !!! row 1
NUF.Assert.That((int)1.499999D, NUF.Is.EqualTo(1));
NUF.Assert.That((int)1.500000D, NUF.Is.EqualTo(1)); // !!! row 2
NUF.Assert.That(System.Convert.ToInt32(0.499999D), NUF.Is.EqualTo(0));
NUF.Assert.That(System.Convert.ToInt32(0.500000D), NUF.Is.EqualTo(0)); // !!!
NUF.Assert.That(System.Convert.ToInt32(1.499999D), NUF.Is.EqualTo(1))开发者_开发问答;
NUF.Assert.That(System.Convert.ToInt32(1.500000D), NUF.Is.EqualTo(2)); //!!! row 3
}
The same double value (1.5D) is converted in different way by casting and Convert.ToInt32 (see row 2 and 3), and two double with same mantissa (0.5 and 1.5) is rounded in different mode (see row 1 and 2). Is it a bug?
Nope, it's documented behaviour. Convert.ToInt32(double)
rounds a number up or down, with half-way points rounding to even:
Return Value
value
, rounded to the nearest 32-bit signed integer. Ifvalue
is halfway between two whole numbers, the even number is returned; that is, 4.5 is converted to 4, and 5.5 is converted to 6.
Casting always rounds towards zero (so 1.8 rounds to one, for example) - from section 6.2.1 of the C# 3 spec:
...
Otherwise, the source operand is rounded towards zero to the nearest integral value. If this integral value is within the range of the destination type then this value is the result of the conversion.
Note that this isn't just about bankers' rounding: it's about rounding in general: there's a difference between (int)0.9
and Convert.ToInt32(0.9)
.
No, it is not a bug. .Net uses banker's rounding by default. If it's not desirable behavior, you can specify the rounding method.
Casting always truncates the number rather than rounding it.
For example, int new = (int)1.999999D;
would give you an int named new with the value 1
.
Convert.ToInt32
says it returns this:
value, rounded to the nearest 32-bit signed integer. If value is halfway between two whole numbers, the even number is returned; that is, 4.5 is converted to 4, and 5.5 is converted to 6.
This is exactly according to both the language spec and the MSDN documentation.
Casting to an integer by design returns the integer part of a floating point number, and the return value of Convert.ToInt32 is rounded to the nearest 32-bit signed integer. If value is halfway between two whole numbers, the even number is returned; that is, 4.5 is converted to 4, and 5.5 is converted to 6.
精彩评论