Prawie cały szeroko dostępny sprzęt korzysta z liczb zmiennoprzecinkowych IETF754, chociaż C++ tego nie wymaga.
Zakładając liczb zmiennoprzecinkowych IETF754 i bezpośrednie odwzorowanie ::std::sqrt
do IETF754 zmiennoprzecinkowej operacji pierwiastkowania, masz pewność, co następuje:
- 16 i 4 mogą zarówno być reprezentowane dokładnie w arytmetyce zmiennoprzecinkowej - w rzeczywistości, numery zmiennoprzecinkowych podwójnej precyzji może reprezentować dowolny 32 bitową liczbę całkowitą dokładnie
- pierwiastek kwadratowy zwraca wynik, który jest najbliżej do bycia dokładny
Dlatego swój przykład will work fine.
Zasadniczo problem, o którym wspomniałeś, może się zdarzyć, ale aby go rozwiązać, musisz zadać większe pytanie: w jakich okolicznościach liczba jest zbliżona do integralnej, naprawdę integralna?
To jest rzeczywiście trudniejsze, niż mogłoby się wydawać, ponieważ chcesz obliczyć podłogę pierwiastka kwadratowego, a zatem po prostu zaokrąglanie nie będzie działać dla ciebie. Jednak, gdy już odpowiesz na to pytanie, wdrożenie rozwiązania powinno być raczej proste. Na przykład:
int i = 16;
int j = std::sqrt(i);
if((j + 1) * (j + 1) == i) j += 1;
int integer = std :: round (floating_point); –
Nieco istotne, jeśli zależy Ci na zaokrągleniu: https://stackoverflow.com/questions/485525/round-for-float-in-c – tux3
@ DieterLücking Myślę, że zaokrąglibyśmy do * najbliższego *, podczas gdy pożądanym rezultatem jest tutaj zaokrąglić w dół od tego, co byłoby "prawdziwym" pierwiastkiem kwadratowym. Na przykład. sqrt (16) -> 4, sqrt (15) -> 3 –