简体   繁体   中英

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. 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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM