Проблема округления VBA
у меня есть эта неясная проблема округления в VBA.
a = 61048.4599674847
b = 154553063.208822
c = a + b
debug.print c
Result:
154614111.66879
вот вопрос, почему VBA округлил переменную c? Я не выдал никакой функции округления. Стоимость я ожидал был 154614111.6687894847. Даже если я округляю или форматирую переменную c до 15 знаков после запятой, я все равно не получаю ожидаемого результата.
любое объяснение было бы оценено.
Edit:
получил ожидаемые результаты с помощью cDec. Я читал это у Джонатана. Ответ Аллена в почему CLng дает разные результаты?
результат теста:
a = cDec(61048.4599674847)
b = cDec(154553063.208822)
c = a + b
?c
154614111.6687894847
2 ответов
причиной является ограниченная точность, которая может храниться в переменной с плавающей точкой.
Для полного объяснения вы должны читать газеты Что Каждый Компьютерщик Должен Знать Об Арифметике С Плавающей Запятой, Дэвид Голдберг, опубликованный в марте 1991 года в номере Computing Surveys.
в VBA тип с плавающей запятой по умолчанию -Double
который является 64-разрядной (8-байтовой) плавающей точкой IEEE число.
есть еще один тип доступный: Decimal
который представляет собой 96-битные (12-байтовые) целые числа со знаком, масштабируемые переменной мощностью 10
Проще говоря, это обеспечивает числа с плавающей запятой до 28-значной точности.
использовать в вашем примере:
a = CDec(61048.4599674847)
b = CDec(154553063.208822)
c = a + b
debug.print c
Result:
154614111.6687894847
Это не неясно, но это не обязательно очевидно.
Я думаю, вы вроде как ответили на него, но основная проблема заключается в одном из" размера " значений, то есть сколько данных можно хранить в переменной данного типа.
Если (и это очень грубо) вы подсчитываете количество цифр в каждом из чисел в первом примере, вы увидите, что у вас есть 15, так что в то время как диапазон значений, которые может представлять float (тип по умолчанию), огромен, точность ограничена до 15 цифр (я уверен, что кто-то будет рядом, чтобы исправить это, я галочки Вики...)
поэтому, когда вы добавляете два числа вместе, он теряет наименее значимые значения, чтобы оставаться в пределах допустимой точности для потока.
выполняя cDec, вы конвертируете в другой тип переменной (decimal), которая способна к большей точности