#include <stdio.h>
int main() {
for (float i = 0; i != 1; i += 0.1) {
printf("%f\n", i);
}
return 0;
}
Czemu pętla nigdy się nie kończy?
#include <stdio.h>
int main() {
for (float i = 0; i != 1; i += 0.1) {
printf("%f\n", i);
}
return 0;
}
Czemu pętla nigdy się nie kończy?
Pewnie chodzi o precyzję floata. Spróbuj tak:
#include <stdio.h>
int main() {
for (float i = 0.0f; i <= 1.0f; i += 0.1f) {
printf("%f\n", i);
}
return 0;
}
Bo dodanie 10x 0.1 nie wynosi w c++ 1, można sobie sprawdzić takim kodem
int main() {
float a = 0;
for (float i = 0; i < 10; i ++) {
a += 0.1;
}
printf(a != 1 ? "Dodanie 10x 0.1 jest różne od 1" : "Dodanie 10x 0.1 jest równe 1");
return 0;
}
Ewentualnie do Twojego kodu dodać warunek i < 2 i wyświetlać dłuższe rozwinięcie
int main() {
for (float i = 0; i != 1 && i < 2; i += 0.1) {
printf("%.23f\n", i);
}
return 0;
}
Wtedy widać że 0.1 to jest tak naprawdę 0.10000000149011611938477
Ogólnie iteracje po floatach i doublach to zły pomysł, kolega wrzucił wyżej przykład
for (float i = 0.0f; i <= 1.0f; i += 0.1f) {
printf("%f\n", i);
}
może się wydawać na pierwszy rzut oka że ostatnie się wypisze 1.000000, ale ostatnie jest 0.900000 ze względu na to o czym pisałem wyżej
Liczby zmiennoprzecinkowe mają skończoną dokładność.
Dodawanie 0.1 binarnie, to coś jak dodawanie 1/3 w systemie dziesiętnym 0.333 + 0.333 + 0.333 = 0.999 a nie 1.0.
Tak jak 1/3 nie da się zaprezentować dokładnie w systemie dziesiętnym, tak 1/10 nie da się dokładnie zaprezentować w systemie binarnym.
Efekt jest taki, że operatory == i != mają ograniczone zastosowanie dla liczb zmiennoprzecinkowych.
Po obliczaniach trzeba uwzględnić jakąś tolerancję. Najbardziej ścisła metoda:
#include <float.h>
#include <stdio.h>
int main() {
for (float i = 0.0f; i < 1.0f - 0.1 * 3 * FLT_EPSILON; i += 0.1f) {
printf("%f\n", i);
}
return 0;
}