Avi Turner
Avi Turner

Reputation: 10456

How come the compiler can't tell the result is an integer

I came across this funny behavior of the compiler:

If I have

    public int GetInt()
    {
        Random rnd = new Random();
        double d = rnd.NextDouble();
        int i = d % 1000;

        return i;
    }

I get an error of: Cannot implicitly convert type 'double' to 'int'. An explicit conversion exists (are you missing a cast?)

which actually makes sense as 1000 can be a double, and the result of the modulo operator might be a double as well.

But after changing the code to:

    public int GetInt()
    {
        Random rnd = new Random();
        double d = rnd.NextDouble();
        int i = d % (int)1000;

        return i;
    }

The error persists.
As far as I can tell, the compiler has all of the information in order to determine that the output of the modulo operator will be an int, so why doesn't it compile?

Upvotes: 0

Views: 113

Answers (6)

Sriram Sakthivel
Sriram Sakthivel

Reputation: 73502

  double d = rnd.NextDouble();
  int i = d % (int)1000;

This code doesn't makes sense. (int)1000 says 1000 is int, but d % (int)1000 says that oh d is double, so compiler has to convert both into a common type Binary numeric promotions mentioned in another answer to make it work.

One thing to understand is that you can't apply any operations with different types, so compiler will convert implicitly for you if there is no loss of data. So (int)1000 will be still converted to double by the compiler before applying operation. so the result will be of type double not int.

Upvotes: 1

Paddy
Paddy

Reputation: 33867

From the documentation:

http://msdn.microsoft.com/en-us/library/0w4e0fzs.aspx

The result of a modulo of a double will be a double. If you need an integer result, then you must:

int i = (int)(d % 1000);

But bear in mind that you are liable to lose data here.


As I slowly engage my brain here - your code doesn't make any sense. NextDouble() will return a value between 0 and 1. There are some logical issues with what you are doing, the result will always be zero, e.g.:

0.15 % 1000 = 0.15

Cast 0.15 to int (always rounds towards zero) -> 0

Upvotes: 1

Random
Random

Reputation: 4779

Compiler will assume you don't want to loose precision of the operation and implicitly use double.

http://msdn.microsoft.com/en-us/library/0w4e0fzs.aspx

Upvotes: 1

Dennis
Dennis

Reputation: 37780

This is by design. See C# language specification:

7.3.6.2 Binary numeric promotions

Binary numeric promotion occurs for the operands of the predefined +, –, *, /, %, &, |, ^, ==, !=, >, <, >=, and <= binary operators. Binary numeric promotion implicitly converts both operands to a common type which, in case of the non-relational operators, also becomes the result type of the operation. Binary numeric promotion consists of applying the following rules, in the order they appear here:

...

  • Otherwise, if either operand is of type double, the other operand is converted to type double.

Upvotes: 2

TylerD87
TylerD87

Reputation: 1618

if d is == to 1500.72546 then the result of the calculation int d % (int)1000 would be 500.72546 so then implicitly casting to an int would result in a loss of data.

Upvotes: 5

Moo-Juice
Moo-Juice

Reputation: 38820

The compiler can tell the result is an integer here, but is being your friend.

Sure, it can automatically convert it for you and not tell you about it and in your trivial example this would be just fine. However, given that converting a double to an int means a LOSS of data, it might well have not been your intention.

If it had not been your intention and the compiler had just gone ahead and done the conversion for you, you could have ended up in a marathon debugging session, devoid of sanity - trying to figure out why a rather esoteric bug as been reported.

This way, the compiler is forcing you to say, as a programmer, "I know I will lose data, it's fine".

Upvotes: 1

Related Questions