Cでは、aとbの両方が整数である整数除算a/bとfloor(a/b)の間に違いはありますか?より具体的には、両方のプロセス中に何が起こりますか?
_a/b
_は整数除算を行います。 a
またはb
のいずれかが負の場合、結果はコンパイラーに依存します(丸めはゼロに向かっているか、C99より前の負の無限大に向かっているかもしれません。C99+では、丸めは0に向かっています)。結果のタイプはint
です。 floor(a/b)
は同じ除算を行い、結果をdoubleに変換し、(存在しない)小数部分を破棄して、結果をdoubleとして返します。
floor
はdouble
を返しますが、a / b
a
とb
の両方が整数である場合、整数値が生成されます。
正しいキャストでは、値は同じです。
typeof
演算子がCに存在する場合(存在しない場合)、次のようになります。
(typeof (a /b)) floor(a / b) == a / b
編集:質問が次の場合:違いはありますか:
(double) (a / b)
そして
floor(a / (double) b)
答えはイエスです。結果は負の値に関して異なります。
整数から浮動小数点に変換する情報が失われる可能性があります。 intとdoubleの可能性は低いですが、わずかな変更があります。
#include <stdio.h>
#include <math.h>
int main(void)
{
unsigned long long a = 9000000000000000003;
unsigned long long b = 3;
printf("a/b = %llu\n", a/b);
printf("floor(a/b) = %f\n", floor(a/b));
return 0;
}
結果:
a/b = 3000000000000000001
floor(a/b) = 3000000000000000000.000000
一般に、整数は整数型と浮動小数点型の両方で表現可能であると仮定すると、違いはありませんが、証明は明らかではありません。問題は、浮動小数点では、丸めが除算a/bで発生するため、floor関数は正確な有理値ではなく、近似値に適用されることです。私はこの件について論文を書きました: https://www.vinc17.net/research/publi.html#Lef2005b
要するに、私が得た結果は、a-bが浮動小数点システムで正確に表現できる場合、a(およびb)が浮動小数点数(整数値を含む)であるfloor(a/b)は、整数除算a/bと同じ結果。