int同士の割り算で小数点以下が切り捨てられる
int型同士を/で割ると、結果もint型になり小数点以下が切り捨てられます。平均値の計算などで意図せず結果が狂う典型的な原因です。
なぜエラーが出ないのか
出力: 3.0
(エラーなし)- Cは何も報告しません。コンパイルも実行も正常に完了するためです
出力: 3.0- 実際の挙動 — 期待した結果と食い違っている箇所
見つけ方- エラーが出ないので、出力を目で確かめるか、コードを目で追うしかありません。この種の誤りが最も発見が遅れます
このエラーが出る典型パターン
パターン1
1 #include <stdio.h> 2 3 int main(void) { 4 int total = 7; 5 int count = 2; 6 double avg = total / count; ^ 7 printf("%.1f\n", avg); 8 return 0; 9 }
int同士の割り算は小数点以下を切り捨てたint型の結果になります。その結果をdoubleに代入しても、切り捨てはもう元に戻りません。片方をdoubleにキャストしてから割る必要があります。
直し方: / を / 1.0 / にします。
パターン2
1 #include <stdio.h> 2 3 int main(void) { 4 int minutes = 100; 5 double hours = minutes / 60; ^ 6 printf("%.2f\n", hours); 7 return 0; 8 }
minutesも60もint型なので、/は整数除算になり小数点以下が切り捨てられます。結果をdouble型の変数に代入しても、切り捨てられた後の値がそのまま入るだけです。
直し方: / を / 1.0 / にします。
パターン3
1 #include <stdio.h> 2 3 int main(void) { 4 int price = 999; 5 int people = 4; 6 double share = price / people; ^ 7 printf("%.2f\n", share); 8 return 0; 9 }
999 / 4は整数除算として計算され249になり、そのあとでdoubleに変換されます。先にdoubleへ変換してから割らない限り、小数部分は復元できません。
直し方: / を / 1.0 / にします。
パターン4
1 #include <stdio.h> 2 3 int main(void) { 4 int wins = 3; 5 int games = 8; 6 double rate = wins / games; ^ 7 printf("%.2f\n", rate); 8 return 0; 9 }
winsもgamesもint型なので、/は整数除算になり小数部分が切り捨てられます。
直し方: / を / 1.0 / にします。
パターン5
1 #include <stdio.h> 2 3 int main(void) { 4 int total = 50; 5 int weeks = 3; 6 double perWeek = total / weeks; ^ 7 printf("%.2f\n", perWeek); 8 return 0; 9 }
整数同士の割り算が先に切り捨てられてからdoubleに代入されるため、あとから小数部分を復元できません。
直し方: / を / 1.0 / にします。
よくある誤解
他の言語の経験から「割り算の結果は自動でdoubleになる」と思いがちですが、Cの/は両辺の型で結果の型が決まります。int同士なら結果もintです。小数を得たい場合は、割る前にどちらかをdoubleにキャストする必要があります。
実務での勘所
負の数が関わる整数除算の丸め方向は、実はC99より前は処理系定義(コンパイラや環境によって結果が変わってもよい)でした。-7 / 2が-3になるか-4になるかは規格上決まっていなかったのです。C99で「ゼロに向かって切り捨てる」という規則に統一され、-7 / 2は必ず-3になることが保証されました。古い時代に書かれたCコードを別の環境に移植する際、この丸め方向の違いが原因で結果が変わることが実際にありました。