2015-06-30 14 views
6

Mam program C++, który działa na obu systemach Windows/Linux. W systemie Windows program jest kompilowany za pomocą Visual Studio 2012 i Linux jest skompilowany z GCC. Przy konwersji podwójnych strun do sprintf wykorzystaniem Visual Studio używa innej metody zaokrąglania niż kompilator GCC dla tej więzi - tj dziesiętne kończąc na 5.C++ Zaokrąglanie zachowanie spójności dla powiązań z sprintf

kompilator Visual Studio wydaje się wykonać round half away from zero natomiast GCC robi round even aka bankierów zaokrągleń.

Runda jest nawet pożądanym zachowaniem.

Czy można zmienić zachowanie zaokrąglania dla ciągów w formacie sprintf w visual studio/windows? Ponieważ potrzebuję, aby zaokrąglenie zachowywało się konsekwentnie między tymi dwoma.

Oto mała próbka C++ program, który ilustruje wyżej opisany problem:

int main() 
{ 
    char buffer[100]; 

    double x; 
    for (x = -0.5; x <= 10.5; x += 1.0) 
    { 
     sprintf(buffer,"%4g %.0f\n", x, x); 

     std::cout << buffer; 
    } 

    return 0; 
} 

wyjście systemu Windows. Liczby są zaokrąglone od zera:

windows

wyjście OSX skompilowany przy użyciu Xcode. Liczby są zaokrąglone użyciu runda nawet w kierunku parzystej liczbie:

wyjście

osx

OSX:

+1

Możesz zajrzeć do tego artykułu i jego komentarzy: http://www.exploringbinary.com/inconsistent-rounding-of-printed-floating-point-numbers/ – NathanOliver

+0

zawsze możesz użyć własnego {*} printf funkcje – technosaurus

+0

[Różnice zaokrąglania w systemie Windows vs Unix w sprintf] (http://stackoverflow.com/q/4649554/995714) –

Odpowiedz

2

To zachowanie wdrożenie zdefiniowane w projekcie C11 standardowej sekcji 7.21.6.1 Funkcją fprintf która obejmuje sprintf względem formatu specyfikatorami a także C++, ponieważ standard C++ opiera się na standardzie C dla funkcji stdio, mówi on o specyfikacji formatu f:

Wartość jest zaokrąglana do odpowiednią liczbę cyfr.

ten obejmuje również defect report 211 którego dodano następujące:

dokładność operacji zmiennoprzecinkowych (+, -, * /) oraz funkcji bibliotekach oraz że zwrot pływającej -point określa implementację, podobnie jak dokładność konwersji między reprezentacjami wewnętrznymi zmiennoprzecinkowymi a reprezentacjami łańcuchów wykonanymi przez procedurę libray w, i. Wdrożenie może stwierdzać, że dokładność nie jest znana.

artykuł Inconsistent Rounding of Printed Floating-Point Numbers obejmuje tę niespójność w wielkich szczegółach i wspomina, że:

glibc printf() został zaktualizowany do podjęcia aktualny tryb IEEE zaokrąglania pod uwagę. Dokonano tego w wersji 2.17; Właśnie przetestowałem go w wersji 2.18. Robiąc to w ten sposób, runda do najbliższego/rundy-połowy-zera-zera nadal nie jest opcją, więc nie pomaga to w osiągnięciu spójności z innymi platformami.

Ale jak powiedział, to nie pomaga w spójność platformy.