C-va
C-va

Reputation: 2910

Integer Conversion in C#

        string[] strArray = new string[10] { "21.65", "30.90", "20.42", "10.00", "14.87", "72.19", "36.00", "45.11", "18.66", "22.22" };
        float temp = 0.0f;
        Int32 resConvert = 0;
        Int32 resCast = 0;
        for (int i = 0; i < strArray.Length; i++)
        {
            float.TryParse(strArray[i], out temp);
            resConvert = Convert.ToInt32(temp * 100);
            resCast = (Int32)(temp * 100);
            Console.WriteLine("Convert: " + resConvert + " ExplCast: " + resCast);
        }

Ans :

   Convert: 2165 ExplCast: 2164   // ??
   Convert: 3090 ExplCast: 3089   // ??
   Convert: 2042 ExplCast: 2042
   Convert: 1000 ExplCast: 1000
   Convert: 1487 ExplCast: 1486   //??
   Convert: 7219 ExplCast: 7219
   Convert: 3600 ExplCast: 3600
   Convert: 4511 ExplCast: 4511
   Convert: 1866 ExplCast: 1865   //??
   Convert: 2222 ExplCast: 2221   //??

Why the value differs sometimes while doing Explicit Cast , but not always. Any reason ?

Upvotes: 14

Views: 4752

Answers (5)

Botz3000
Botz3000

Reputation: 39600

Convert.ToInt32 rounds to the nearest integer, the direct cast just truncates the number.

So, if you, due to floating point imprecision, have a value of 2165.99999whatever instead of 2165.0, the direct cast truncates all after the floating point, while Convert.ToInt32 rounds to the nearest integer.

Example:
22.22f * 100.0f results in something like 2221.99993133544921875.
So Convert.ToInt32 will round it up to the expected value 2222, while the cast will truncate it to 2221.

45.11f * 100.0f on the other hand results in about 4511.00006103515625,
which Convert.ToInt32 rounds down, which results in 4511, the same result as when casting directly.

Upvotes: 4

Grynn
Grynn

Reputation: 1284

Calling Convert.ToInt32 is like calling:

(int) Math.Round(floatValue, 0);

Direct Casting is like calling

(int) Math.Floor(float);

Floor always gives you a value less than or equal to the value you supply in the argument. Floating point representations are not "precise". So 21.65 is probably represented as 21.649999 or similar since there is not enough precision.

So: 21.65 *100 = 2164.9999 Flooring this value should give you an integer which is smaller than or equal to 2164.9 ... ie: 2164

Rounding 2164.99 on the other hand would give you: 2165

You can see the effect here:

Console.WriteLine(Math.Round(21.65f*100));  //2165
Console.WriteLine(Math.Floor(21.65f*100));  //2164

Using doubles instead of float's (more precision, but still not infinite):

Console.WriteLine(Math.Round(21.65d*100));  //2165
Console.WriteLine(Math.Floor(21.65d*100));  //2165

Upvotes: 1

Indy9000
Indy9000

Reputation: 8851

Following from Botz3000 answer, Relevent sections from MSDN:

Convert.ToInt32 Method (Single)

Return Value Type: System.Int32 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.

Explicit Numeric Conversions Table

•When you convert from a double or float value to an integral type, the value is rounded towards zero to the nearest integral value. If the resulting integral value is outside the range of the destination value, the result depends on the overflow checking context. In a checked context, an OverflowException is thrown, while in an unchecked context, the result is an unspecified value of the destination type.

Upvotes: 2

Gabe
Gabe

Reputation: 86698

To take one example, 21.65 in float format is actually represented by a number like 21.6499999. The Convert.ToInt32 rounds the number to the nearest integer, yielding 21.65, while the explicit cast (Int32) just truncates (rounding toward zero), so you get 21.64.

If you want the floating point numbers to be represented in the computer the same way they look printed out, use decimal instead of float or double.

Upvotes: 9

Kane
Kane

Reputation: 16802

I think you will find the problem is caused by inaccuracies with floating point precision, specifically using a float. You will find the issue disappears when using a decimal. There is a really good answer on the differences between decimal and double (and float) here: decimal vs double! - Which one should I use and when?

Upvotes: 1

Related Questions