开发者

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.MaxV开发者_JS百科alue * 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]

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜