Różnice tkwią w zwracanej wartości, podając dane wejściowe dotyczące rozstrzygania remisów, jak sądzę, na przykład ten kod :
int main()
{
std::cout.precision(100);
double input = std::nextafter(0.05, 0.0) / 0.1;
double x1 = floor(0.5 + input);
double x2 = round(input);
std::cout << x1 << std::endl;
std::cout << x2 << std::endl;
}
które wyjścia:
1
0
Ale w końcu to tylko różne wyniki, wybiera się ten preferowany. Widzę wiele "starych" programów C / C ++ używających floor(0.5 + input)
zamiast round(input)
.
Czy jest jakiś historyczny powód? Najtańszy na CPU?
Odpowiedzi:
std::round
została wprowadzona w C ++ 11. Wcześniejstd::floor
był dostępny tylko, więc używali go programiści.źródło
Nie ma żadnego historycznego powodu. Ten rodzaj dewiacji istnieje od roku Dot. Ludzie robią to, gdy czują się bardzo, bardzo niegrzeczni. Jest to nadużycie arytmetyki zmiennoprzecinkowej i wielu doświadczonych zawodowych programistów się na to daje. Nawet elementy Java działały do wersji 1.7. Śmieszni goście.
Moje przypuszczenie jest takie, że przyzwoita, gotowa do użycia, niemiecka funkcja zaokrąglania nie była formalnie dostępna aż do C ++ 11 (pomimo, że C dostał swoje w C99), ale to naprawdę nie jest wymówką dla przyjęcia tak zwanej alternatywy.
Oto rzecz:
floor(0.5 + input)
nie zawsze odzyskuje ten sam wynik, co odpowiedniestd::round
połączenie!Powód jest dość subtelny: punkt odcięcia dla zaokrąglenia niemieckiego
a.5
dla liczby całkowiteja
jest, przez przypadkową właściwość Wszechświata, diadą racjonalną . Ponieważ można to dokładnie przedstawić w zmiennoprzecinkowym IEEE754 do 52 potęgi 2, a następnie zaokrąglanie jest i tak niestd::round
działa , zawsze działa poprawnie. W przypadku innych schematów zmiennoprzecinkowych zapoznaj się z dokumentacją.Ale dodanie
0.5
do adouble
może wprowadzić niedokładność, powodując niewielkie niedokonanie lub przeregulowanie dla niektórych wartości. Jeśli się nad tym zastanowić, dodanie do siebie dwóchdouble
wartości - które są początkiem nieświadomych konwersji denarów - i zastosowanie funkcji, która jest bardzo silną funkcją danych wejściowych (na przykład funkcja zaokrąglania), z pewnością zakończy się łzami.Nie rób tego .
Odniesienie: Dlaczego Math.round (0.49999999999999994) zwraca 1?
źródło
nearbyint()
jest zwykle lepszym wyborem niżround()
, ponieważnearbyint
używa obecnego trybu zaokrąglania zamiast funky tiebreak od zeraround()
(który x86 nie ma nawet wsparcia sprzętowego, chociaż ARM ma). Oba zostały dodane do C ++ w C ++ 11.Myślę, że tutaj się mylisz:
Tak nie jest. Musisz wybrać odpowiedni schemat zaokrąglania domeny . W aplikacji finansowej będziesz obchodzić się zgodnie z regułami bankiera (przy okazji nie używając float). Jednak podczas próbkowania zaokrąglanie w górę przy użyciu
static_cast<int>(floor(f + .5))
daje mniejszy szum próbkowania, co zwiększa zakres dynamiczny. Podczas wyrównywania pikseli, tj. Konwertowania pozycji na współrzędne ekranu, użycie dowolnej innej metody zaokrąglania spowoduje powstanie dziur, luk i innych artefaktów.źródło
Prosty powód może być taki, że istnieją różne metody zaokrąglania liczb, więc jeśli nie znasz stosowanej metody, możesz uzyskać inne wyniki.
Dzięki floor () możesz być spójny z wynikami. Jeśli liczba zmiennoprzecinkowa wynosi .5 lub więcej, dodanie jej spowoduje skok do następnego int. Ale 0,49999 po prostu pominie przecinek.
źródło
round()
powoduje.floor(x + 0.5)
robi, jest błędna .nearbyint(x)
, która używa rozsądnego (do najbliższego parzystego) zaokrąglenia, pod warunkiem, że nie zepsułeś środowiska zmiennoprzecinkowego.Wielu programistów dostosowuje idiomy, których nauczyli się podczas programowania w innych językach. Nie wszystkie języki mają
round()
funkcję iw tych językach normalne jest użycie jejfloor(x + 0.5)
jako substytutu. Kiedy ci programiści zaczynają używać C ++, nie zawsze zdają sobie sprawę, że jest coś wbudowanegoround()
, nadal używają stylu, do którego są przyzwyczajeni.Innymi słowy, tylko dlatego, że widzisz dużo kodu, który coś robi, nie oznacza to, że istnieje dobry powód, aby to zrobić. Przykłady tego można znaleźć w każdym języku programowania. Pamiętaj o prawie Jesiotra :
źródło