2011-09-07 14 views
6

Mam problem z zaokrąglaniem w VBA.Problem zaokrąglania VBA

a = 61048.4599674847 
b = 154553063.208822 
c = a + b 
debug.print c 
Result: 
154614111.66879 

Oto pytanie, dlaczego VBA zaokrąglił zmienną c? Nie wydałem żadnej funkcji zaokrąglania. Oczekiwana wartość wyniosła 154614111.6687894847. Nawet jeśli zaokrąglę lub sformatuję zmienną c na 15 miejsc po przecinku, nadal nie otrzymam oczekiwanego wyniku.

Wszelkie wyjaśnienia byłyby mile widziane.

Edytuj:

Otrzymałem oczekiwane wyniki przy użyciu cDEC. Czytałem to w odpowiedzi Jonathan Allena w Why does CLng produce different results?

Oto wynik do testu:

a = cDec(61048.4599674847) 
b = cDec(154553063.208822) 
c = a + b 
?c 
154614111.6687894847 
+1

[arytmetyki zmiennoprzecinkowej może dawać niedokładne wyniki w programie Excel] (http://support.microsoft .com/kb/78113) – SeanC

Odpowiedz

11

Powodem jest ograniczony precission które mogą być przechowywane w zmiennej liczb zmiennoprzecinkowych.
Aby uzyskać pełne wyjaśnienie, należy przeczytać artykuł: Co każdy informatyk powinien wiedzieć o pływającej arytmetyki, autorstwa Davida Goldberga, opublikowanej w marcowym wydaniu z 1991 r. W ankiecie komputerowej.

Link to paper

VBA domyślny swobodna punkt jest Double który jest IEEE 64-bitowe (8 bajtów) Numer zmiennoprzecinkową.

Jest jeszcze inny rodzaj dostępnych: Decimal który jest 96-bitowy (12 bajtów) podpisały całkowitymi skalowane o zmiennej sile 10
Mówiąc prościej, to zapewnia liczb zmiennoprzecinkowych do 28 cyfr precission.

do wykorzystania w przykładzie:

a = CDec(61048.4599674847) 
b = CDec(154553063.208822) 
c = a + b 
debug.print c 
Result: 
154614111.6687894847 
+0

Dzięki za link. – Grekoz

3

jej nie niejasne, ale jego niekoniecznie oczywiste.

Myślę, że odpowiedziałeś na to pytanie - ale podstawowym problemem jest "wielkość" wartości, czyli ile danych może być przechowywanych w zmiennej danego typu.

Jeśli (i to jest bardzo prymitywne) zliczasz liczbę cyfr w każdym z numerów w pierwszym przykładzie, zobaczysz, że masz 15, podczas gdy zakres wartości, które float (typ domyślny) może reprezentować jest ogromna, precyzja jest ograniczona do 15 cyfr (jestem pewna, że ​​ktoś będzie to poprawiał, zaznaczę pole wiki ...)

Tak więc po dodaniu tych dwóch liczb tracisz najmniej znaczące wartości, aby pozostać w dopuszczalnej dokładności dla przepływu.

Wykonując CDec jesteś konwersji do innego typu zmiennej (po przecinku), która jest zdolna do większej precyzji