When a calculation is made in C#, is the primitive type of the variable maintained in the result?

Asked

Viewed 95 times

2

I’m creating a simple C# application to calculate some flight information, in which you have a class called Calculator containing the following methods:

public static float GetDistance(ushort height) {
    return height * 3 / 1000;
}

public static uint GetVerticalSpeed(ushort groundSpeed) {
    return groundSpeed * 10 / 2;
}

In both methods, I defined the parameters as being of the primitive type ushort, for they must be equal to or greater than zero, and must have a certain limit, since no aircraft flies above 65536 ft altitude and above 65536 knots speed - which is the maximum value of this primitive type.

The primitive type of return methods is different. In the first method, the return is float, because I need to get the decimals of the result. Already in the second method, the return is uint, as the result may be greater than 65535.

The problem is that even having the primitive type of return "compatible" with the maximum result that the method can return, the compiler still generates the following error for the second method:

Cannot implicitly convert type 'int' to 'uint'. An explicit conversion exists (are you missing a cast?)

Also, in the first method, the returned result is always an integer - no floating point - even when it should be a real number.

This leads me to think that the problem of my code is not in the return of methods, but in the line of calculation. I wrote the methods thinking that the calculation would return a value, whose primitive type would correspond to the result. But it seems that’s not what happens.

That said, my question is:

  • Arithmetic operations in C# keeps the primitive type of the variable used in the result?
  • If yes, how this occurs internally and what I should do to make the result have a primitive type different from the variable?
  • yes, the compiler does not know how to do this, need for a cast ai in the code to convert to the desired type, in that case uint.About your question, the type of variable is immutable if it is int for example, it will always be int, and so on. And second question as I mentioned, just make a cast and convert to desired type

  • 1

    Just to complement, the Typecast explicitly return (uint)(groundSpeed * 10 / 2);

1 answer

6


In the case of division into C#, the compiler will base the type of evaluation on the type of operands.

If all the operands in the division have an integer type, then the operator / will return as a result of entire division of his two operands.

For example:

5 / 2      //=> 2

It is evaluated by C# as 2. Since the two operands are integer, the entire division occurs.

If you want to operate a "floating point division", you must make a cast explicit of at least one of the operands. You can use the literal syntax:

5f / 2      //=> 2.5
5 / 2f      //=> 2.5
5f / 2f     //=> 2.5

Or use the syntax of cast:

(float)5 / 2            //=> 2.5
5 / (float)2            //=> 2.5
(float)5 / (float)2     //=> 2.5

Of course, you could also do the cast for double or decimal, if necessary.


For the second method and for the conversion of uint for int:

The problem is that even having the primitive type of return "compatible" with the maximum result that the method can return, the compiler still generates the following error for the second method:

I would not say that it is fully compatible. After all, the result of the expression (inferred by the compiler) is int. And I’m sure, int will not always be compatible with uint.

Thus, the compiler requires you to be explicit when doing this type of cast. Like there may be data loss (say you convert a int negative for uint, would give problem), you need to show that "you are aware of this".

So you gotta do it like this:

public static uint GetVerticalSpeed(ushort groundSpeed)
{
    return (uint)(groundSpeed * 10 / 2);
}

Or simply ensure that the numbers at the end are uint for the compiler to evaluate the expression type for uint. Thus:

public static uint GetVerticalSpeed(ushort groundSpeed)
{
    return groundSpeed * (uint)10 / (uint)2;
}

But generally use numerical types unsigned in response to some domain rule (such as the fact that an object cannot have negative velocity) may not justify the use of a type unsigned.

As explained in I must use the types ushort, uint and ulong whenever the number is equal to or greater than 0?, think of unsigned numerical types as a "subset" of natural numbers not always a good idea, since the guy, by itself, may not guarantee the stored value.

Here also has some more details.

In short, use int (or maybe a short same) in your code would probably simplify things (besides making some Casts unnecessary). If you need to guarantee a "speed limit" (in response to some domain rule), treat this explicitly in your code.

  • 1

    Thanks Luiz! Oh, and taking advantage. I haven’t been in Discord for a while because my net was cut and I don’t have a deadline when it will return ;(

  • Luiz, I wrote the line using the first form you presented, but without isolating the calculation with the parentheses, this way: return (uint) groundSpeed * 10 / 2. Still, it worked. Why?

  • The compiler will understand the cast that you are doing the same way. This behavior is expected.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.