C#の整数除算が浮動小数点数ではなく整数を返す理由を誰もが知っていますか?その背後にあるアイデアは何ですか? (それはC/C++のレガシーのみですか?)
C#の場合:
float x = 13 / 4;
//imagine I used have an overridden == operator here to use epsilon compare
if (x == 3.0)
print 'Hello world';
このコードの結果は次のようになります。
'Hello world'
厳密に言えば、整数除算のようなものはありません(定義による除算は有理数を生成する演算であり、整数はその非常に小さなサブセットです)。
新しいプログラマーが実際に浮動小数点除算を使用するつもりだったときに整数除算を実行するというこの間違いを犯すのは一般的ですが、実際には整数除算は非常に一般的な操作です。人々がめったにそれを使用しないと仮定し、除算を行うたびに常に浮動小数点にキャストすることを覚えておく必要があると仮定している場合、あなたは間違っています。
まず、整数除算はかなり高速であるため、整数の結果のみが必要な場合は、より効率的なアルゴリズムを使用する必要があります。
第二に、整数除算を使用するアルゴリズムがいくつかあり、除算の結果が常に浮動小数点数である場合、毎回結果を丸める必要があります。私の頭の一番上の例は、数値の基数を変更することです。各桁の計算には、数値の浮動小数点除算ではなく、数値と整数の整数除算が含まれます。
これらの(および他の関連する)理由により、整数の除算は整数になります。 2つの整数の浮動小数点除算を取得する場合は、1つをdouble
/float
/decimal
にキャストすることを忘れないでください。
C# specification を参照してください。除算演算子には3つのタイプがあります
あなたの場合、次の規則が適用された整数除算があります。
除算は結果をゼロに丸め、結果の絶対値は2つのオペランドの商の絶対値よりも小さい可能な最大の整数です。 2つのオペランドの符号が同じ場合、結果はゼロまたは正になり、2つのオペランドの符号が反対の場合、結果はゼロまたは負になります。
C#が整数にこのタイプの除算を使用する理由(一部の言語は浮動小数点の結果を返す)は、ハードウェア-整数除算がより高速で簡単だと思います。
各データ型は、各演算子をオーバーロードできます。分子と分母の両方が整数の場合、整数型は除算演算を実行し、整数型を返します。浮動小数点除算が必要な場合は、1つ以上の数値を浮動小数点型にキャストしてから分割する必要があります。例えば:
int x = 13;
int y = 4;
float x = (float)y / (float)z;
または、リテラルを使用している場合:
float x = 13f / 4f;
浮動小数点は正確ではないことに注意してください。精度を重視する場合は、代わりにdecimal型などを使用してください。
サフィックスを使用しないため、リテラル13
および4
は整数として解釈されます。
手動 :
リテラルに接尾辞がない場合、その値を表すことができるこれらのタイプの最初のものがあります:
int
、uint
、long
、ulong
。
したがって、13
を整数として宣言するため、整数除算が実行されます。
手動 :
X/yの形式の操作では、特定の演算子の実装を選択するために、バイナリ演算子のオーバーロード解決が適用されます。オペランドは、選択した演算子のパラメーター型に変換され、結果の型は演算子の戻り型です。
定義済みの除算演算子を以下にリストします。演算子はすべて、xとyの商を計算します。
整数除算:
int operator /(int x, int y); uint operator /(uint x, uint y); long operator /(long x, long y); ulong operator /(ulong x, ulong y);
そして、切り捨てが発生します:
除算は結果をゼロに丸め、結果の絶対値は2つのオペランドの商の絶対値よりも小さい可能な最大の整数です。 2つのオペランドの符号が同じ場合、結果はゼロまたは正になり、2つのオペランドの符号が反対の場合、結果はゼロまたは負になります。
以下を行う場合:
int x = 13f / 4f;
浮動小数点除算(/
演算子の13f
演算子)がfloatになり、暗黙的にintにキャストできないため、コンパイラエラーが発生します。
除算を浮動小数点除算にする場合、結果を浮動小数点にする必要があります。
float x = 13 / 4;
整数を分割することに注意してください。これは暗黙的にfloatにキャストされ、結果は3.0
になります。 f
サフィックス(13f
、4f
)を使用して、オペランドを明示的にfloatとして宣言します。
その単なる基本操作。
いつ分割を学んだかを覚えておいてください。最初に9/6 = 1 with remainder 3
を解決しました。
9 / 6 == 1 //true
9 % 6 == 3 // true
/ -operatorと%-operatorを組み合わせて使用して、これらの値を取得します。
役に立つかもしれません:
double a = 5.0/2.0;
Console.WriteLine (a); // 2.5
double b = 5/2;
Console.WriteLine (b); // 2
int c = 5/2;
Console.WriteLine (c); // 2
double d = 5f/2f;
Console.WriteLine (d); // 2.5
結果は常に、分子と分母の範囲が広いタイプになります。例外はbyteとshortであり、int(Int32)を生成します。
var a = (byte)5 / (byte)2; // 2 (Int32)
var b = (short)5 / (byte)2; // 2 (Int32)
var c = 5 / 2; // 2 (Int32)
var d = 5 / 2U; // 2 (UInt32)
var e = 5L / 2U; // 2 (Int64)
var f = 5L / 2UL; // 2 (UInt64)
var g = 5F / 2UL; // 2.5 (Single/float)
var h = 5F / 2D; // 2.5 (Double)
var i = 5.0 / 2F; // 2.5 (Double)
var j = 5M / 2; // 2.5 (Decimal)
var k = 5M / 2F; // Not allowed
浮動小数点型と10進数型の間の暗黙的な変換はないため、それらの間の除算は許可されません。明示的にキャストし、どれを使用するかを決定する必要があります(10進数は、浮動小数点型に比べて精度が高く、範囲が狭くなります)。