多くの暗黙的な変換が発生していますが、そのほとんどは不要です。
unsigned long long int a = 17446744073709551615;
接尾辞なしの 10 進整数リテラルの型int
は 、long int
、またはlong long int
です。署名されていないタイプではありません。その特定の値は、ほぼ確実に a long long int
(2 63 -1) の最大値を超えています。コンパイラが 64 ビットを超える符号付き整数型を持っていない限り、プログラムの形式が正しくありません。
ULL
リテラルが正しい型であることを確認するためにサフィックスを追加します。
unsigned long long int a = 17446744073709551615ULL;
値はたまたま 2 63 -1 から 2 64 -1 の間であるため、64 ビット符号なし型には適合しますが、64 ビット符号付き型には適合しません。
(実際には だけでU
十分ですが、明示的にしても害はありません。)
signed long long int b = -30000000003;
これは問題にはなりません。30000000003
符号付き整数型です。コンパイラlong long
が少なくとも 64 ビット幅の をサポートしている場合、オーバーフローはありません。それでも、 の値に接尾辞が必要な限り、a
明示的に指定しても問題ありません。
signed long long int b = -30000000003LL;
これで、次のようになりました。
signed int c;
c = a/b;
unsigned long long
を a で割るsigned long long
と、符号付きオペランドが に変換されunsigned long long
ます。この場合、変換される値は負であるため、大きな正の値に変換されます。利回りに変換-30000000003
します。で割るとゼロになります。unsigned long long
18446744043709551613
17446744073709551615
18446744043709551613
コンパイラが 64 ビットを超える整数をサポートしていない限り (ほとんどの場合サポートしていません)、直接除算17446744073709551615
し-30000000003
て数学的に正しい答えを得ることができません。これは、両方の値を表すことができる整数型がないためです。すべての算術演算子 (シフト演算子を除く) には、同じ型のオペランドが必要であり、必要に応じて暗黙的な変換が適用されます。
この特定のケースでは、除算17446744073709551615ULL
し30000000003ULL
て符号を考慮することができます。(負の整数の除算については、言語規則を確認してください。)
一般的にこれを本当に行う必要がある場合は、浮動小数点に頼ることができます (つまり、精度がいくらか失われる可能性があります) か、GMPのような任意幅の整数演算パッケージを使用できます。