2009-07-20 5 views
5

Próbuję przenieść kod Javy do C++. Natknąłem się na dziwne zachowanie. Nie mogę uzyskać podwójnego dodatku do pracy (nawet jeśli opcja kompilacji/fp: strict oznacza, że ​​"poprawna" zmiennoprzecinkowa matematyka jest ustawiona w Visual Studio 2008).Dlaczego liczby podwójne są niepoprawnie dodane w konkretnym projekcie programu Visual Studio 2008?

double a = 0.4; 
/* a: 0.40000000000000002, correct */ 

double b = 0.0 + 0.4; 
/* b: 0.40000000596046448, incorrect 
(0 + 0.4 is the same). It's not even close to correct. */ 

double c = 0; 
float f = 0.4f; 
c += f; 
/* c: 0.40000000596046448 too */ 

W innym projekcie testowym, który skonfigurowałem, działa poprawnie (/ fp: strict zachowuje się zgodnie z IEEE754).

Korzystanie z Visual Studio 2008 (standard) bez opcji Optymalizacja i FP: ścisły.

Wszelkie pomysły? Czy naprawdę przycina się do pływaków? Ten projekt naprawdę wymaga takiego samego zachowania zarówno po stronie java, jak i C++. Mam wszystkie wartości, czytając z okna debugowania w VC++.

Rozwiązanie: _fpreset(); // Pomysł Barry Kelly rozwiązał to. Biblioteka ustawiła precyzję FP na niską.

+2

Czy możesz zamieścić mały kompletny program testowy wraz z wiersza polecenia używanego do kompilacji (patrz okno wyjściowe itp.), Który pokazuje problem? Jedyny sposób, w jaki mogę się rozmnażać, to użycie zamiast tego 0,0f + 0,4f. –

+0

Czy możemy przyjąć, że wiesz o niedokładności typów zmiennoprzecinkowych? Dokładność z dokładnością do 7 miejsc po przecinku jest zwykle uważana za prawidłową, ponieważ domyślna precyzja drukowania wynosi 6. –

+0

@Evan, jego przykład jest wyłączony o więcej, niż wynikałoby to z niedokładności zmiennoprzecinkowej. – Kevin

Odpowiedz

8

Jedyne, co mogę wymyślić, to być może łączysz się z biblioteką lub biblioteką DLL, która zmodyfikowała precyzję procesora za pomocą słowa kontrolnego.

Czy próbowałeś zadzwonić pod numer _fpreset() z float.h przed problematycznym obliczeniem?

+0

To musi być coś podobnego, ale jest 0,0 + 0,4 nawet obliczenia? Czy nie można go ocenić podczas kompilacji? Sprawdzanie demontażu może ustalić, czy tryb float w środowisku wykonawczym ma coś z tym wspólnego, czy też coś poszło nie tak podczas kompilacji. –

+0

Oczywiście, może tak być, ale gdyby to było tak proste, byłoby łatwo je odtworzyć, nie? –

+0

Nie wiem, może coś innego w projekcie określa/fp: głupi lub równoważny. Moim osobistym faworytem jest plik źródłowy, który nie jest zakończony znakiem nowej linii, a zatem program ma niezdefiniowane zachowanie, chociaż nie mam nadziei, że kiedykolwiek zobaczę, że powoduje to błąd na wolności ... –

3

Tak, z pewnością przycina się do elementów pływających. Otrzymuję tę samą wartość drukowania, co w przypadku "niedokładności". Wypróbuj:

double b = 0.0 + (double) 0.4; 

Pytanie brzmi, dlaczego jest on obcinany do elementów pływających. W standardzie nie ma usprawiedliwienia dla traktowania 0.0 + 0.4 jako wyrażenia o pojedynczej precyzji, ponieważ liczby zmiennoprzecinkowe są podwójną precyzją, chyba że mają przyrostek, aby powiedzieć inaczej.

Coś musi ingerować w twoje ustawienia, ale nie mam pojęcia co.

Powiązane problemy