Точность отладчика VBA

У меня есть single который я считаю, что эквивалент C ++ float в VBA в модуле книги Excel. В любом случае, первоначально назначенное мной значение (876,34497) округляется до 876,345 в «Немедленном окне» и «Подсказка» и всплывающей подсказке, когда я устанавливаю точку останова на VBA. Однако, если я пройду это Single в C ++ DLL C ++ сообщает об этом как исходное значение 876.34497.

Итак, действительно ли оно хранится в памяти как исходное значение? Это какое-то ограничение отладчика? Не уверены, что здесь происходит. Трудно проверить, является ли то, что я передаю, тем, что я получаю на стороне C ++.

введите описание изображения здесь

Я старался:

?CStr(test)
876.345
?CDbl(test)
876.344970703125
?CSng(test)
876.345

VBA не очень прост, поэтому на каком-то уровне он должен храниться в памяти как 876.34497. В противном случае я не думаю, CDbl было бы правильно, как это.

4

Решение

Переменные VBA типа «single» хранятся как «32-битная аппаратная реализация IEEE 754 [-] 1985 [sic]». [увидеть: https://msdn.microsoft.com/en-us/library/ee177324.aspx].

На английском языке это означает, что «одинарные» числа точности преобразуются в двоичные, а затем усекаются до 4-байтовой (32-разрядной) последовательности. Точный процесс очень хорошо описан в Википедии под http://en.wikipedia.org/wiki/Single-precision_floating-point_format . В результате все числа одинарной точности выражаются как

(1) a 23 bit "fraction" between 0 and 1, *times*
(2) an 8-bit exponent which represents a multiplier between 2^(-127) and 2^128, *times*
(3) one more bit for positive or negative.

Процесс преобразования чисел в двоичные и обратно вызывает два типа ошибок округления:

(1) Значимые цифры — как вы заметили, существует ограничение на значащие цифры. 22-битное целое число может иметь только 8,388,607 уникальных значений. Другими словами, ни одно число не может быть выражено с точностью более +/- 0,000012%. Возвращаясь к науке о старшей школе, вы можете вспомнить, что это еще один способ сказать, что вы не можете рассчитывать на более чем шесть значащих цифр (ну, десятичные цифры, по крайней мере … конечно, у вас есть 22 значащие двоичные цифры). Таким образом, любое представление числа с более чем шестью значащими цифрами будет округлено. Однако, оно не будет округлено до ближайшей десятичной цифры … оно будет округлено до ближайшей двоичной цифры. Это часто приводит к неожиданным результатам (как у вас).

(2) Двоичное преобразование. Другой тип ошибок еще более пагубен. Есть некоторые числа со значительно менее чем шестью (десятичными) цифрами, которые будут округлены. Например, 1/5 в десятичном виде — это 0.2000000. Он никогда не округляется. Но то же самое число в двоичном виде — 0,00110011001100110011 …. повторяется вечно. (Эта последовательность эквивалентна 1/8 + 1/16 + 1/16 * (1/8 + 1/16) + 1/256 * (1/8 + 1/16) …) Если вы использовали произвольный число двоичных цифр для представления 0,20, а затем преобразовать его обратно в десятичную, вы никогда не получите точно 0,20. Например, если вы использовали восемь битов, у вас было бы 0,00110011 в двоичном формате, что:

  0.12500000
0.06250000
0.00781250
+ 0.00390625
------------
0.19921875

Независимо от того, сколько двоичных цифр вы используете, вы никогда не получите точно 0,20, потому что 0,20 нельзя выразить как сумму степеней двух.

Это в двух словах объясняет, что происходит. Когда вы назначаете 876.34497 для «теста», он конвертируется внутри:

1 10001000 0110110001011000010011
136       5,969,427

Который (+1) * 2 ^ (136-127) * (5,969,427) / (2 ^ 23)

Excel автоматически усекает отображение вашего номера с одинарной точностью, чтобы показать только шесть значащих цифр, потому что он знает, что седьмая цифра может быть неправильной. Я не могу сказать вам, что это за номер, потому что мой Excel не отображает достаточно значащих цифр! Но вы поняли.

Когда вы приводите значение к двойной точности, оно использует всю двоичную строку, а затем добавляет в ноль еще 4 байта нулей. Теперь он позволяет отображать вдвое больше значащих цифр, потому что это двойная точность, но, как вы можете видеть, преобразование из 8 десятичных цифр в 23 двоичных цифры и последующее добавление еще одной длинной строки нулей привело к некоторым ошибкам. Не совсем ошибки, если вы понимаете, что он делает; просто артефакты. В конце концов, он делает именно то, что вы сказали, чтобы сделать … вы просто не знали, что вы говорите, что делать!

1

Другие решения


По вопросам рекламы [email protected]