Cでは、aとbの両方が整数である整数除算a/bとfloor(a/b)に違いはありますか? より具体的には、両方のプロセスで何が起こるのでしょうか?
4 に答える
a/b
整数除算を行います。またはが負のa
場合b
、結果はコンパイラによって異なります (C99 より前では、丸めはゼロまたは負の無限大に向かって行われます。C99+ では、丸めは 0 に向かって行われます)。結果の型はint
です。floor(a/b)
同じ除算を行い、結果を double に変換し、(存在しない) 小数部分を破棄して、結果を double として返します。
floor
との両方が整数であるdouble
while を返すと、整数値が得られます。a / b
a
b
正しいキャストでは、値は同じです。
演算子が C に存在する場合typeof
(存在しない場合)、次のようになります。
(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 で丸めが発生するため、フロア関数が正確な有理値ではなく近似値に適用されることです。私はこの件について論文を書きました: https://www.vinc17.net/research/publi.html#Lef2005b
要するに、私が得た結果は、a - b が浮動小数点システムで正確に表現できる場合、floor(a/b) (a と b は浮動小数点数 (整数値)) であるということです。整数除算 a/b と同じ結果になります。