# math - C# Arithmetic Question

Good afternoon,

Having never used C# to do serious mathematical work, I have just noticed something which left me confused... If it is true that

``double Test = Math.Sqrt(UInt64.MaxValue)``

is equal to 4294967296.0, that is, `UInt32.MaxValue + 1`, why is it that

``ulong Test2 = UInt32.MaxValue * UInt32.MaxValue;``

is equal to 1? At first sight it seems to me that overflow occurs here... But why is that since that product should fit a `UInt64`?

Thank you very much.

the first one happens because double doesn't have 64 mantissa bits, but only around 53. So `UInt64.MaxValue` will be rounded to `UInt64.MaxValue+1` during the conversion to `double`. And the `Sqrt` of that is obviously 2^32. `double` can represent any value from `(U)Int32` exactly, but some of the larger 64 bit integers can't be represented as `double`.

The second one happens because you do the multiplication before casting to `UInt64`, i.e. it happens as `UInt32`, which obviously overflows. Cast at least one of your operands to `UInt64` and the problem will disappear.

``````ulong Test2 = UInt32.MaxValue * UInt32.MaxValue
``````

Could be translated to :

``````UInt32 __temp = UInt32.MaxValue * UInt32.MaxValue; // Overflow
ulong Test2 = (ulong)__temp;
``````

as thee operation on the left of the = sign is always done without any inference on the type on the right obviously not what you want...

It should have been

``````ulong Test2 = (long)UInt32.MaxValue * UInt32.MaxValue;
``````

That will be treated as :

``````ulong Test2 = (long)UInt32.MaxValue * (long)UInt32.MaxValue;
``````

And will work.

The rules are in section 16.4.2 of the C# norm :

Numeric promotion consists of automatically performing certain implicit conversions of the operands of the predefined unary and binary numeric operators. Numeric promotion is not a distinct mechanism, but rather an effect of applying overload resolution to the predefined operators. Numeric promotion specifically does not affect evaluation of user-defined operators, although user-defined operators can be implemented to exhibit similar effects.

As an example of numeric promotion, consider the predefined implementations of the binary * operator:

``````int operator *(int x, int y);
uint operator *(uint x, uint y);
long operator *(long x, long y);
ulong operator *(ulong x, ulong y);
void operator *(long x, ulong y);
void operator *(ulong x, long y);
float operator *(float x, float y);
double operator *(double x, double y);
decimal operator *(decimal x, decimal y);
``````

When overload resolution rules (§14.4.2) are applied to this set of operators, the effect is to select the first of the operators for which implicit conversions exist from the operand types. [Example: For the operation b * s, where b is a byte and s is a short, overload resolution selects operator *(int, int) as the best operator. Thus, the effect is that b and s are converted to int, and the type of the result is int. Likewise, for the operation i * d, where i is an int and d is a double, overload resolution selects operator *(double, double) as the best operator. end example]