Михаил Орлов писал(а):Из книги Джона Уокенбаха "Профессиональное программирование на VBA" я запомнил тип этого свойства, как Double.
Потом обнаружил, что VBA/Excell 64 возвращает в этом свойстве тип LongLong (точнее - Variant, subtype LongLong),
решил, что VBA/Excell 64 возвращает LongLong, а VBA/Excell 32 - Double, решил проверить и... обнаружил,
что VBA/Excell 32 тоже возвращает LongLong (Variant, subtype LongLong).
Ещё Была мысль, что в VBA/Excell 2007 32 свойство Range.CountLarge возвращало тип Double, и тип изменился с версией MS-Office,
Ну Double было бы опрометчиво использовать в связи с перспективой потери точности для целых чисел. Для числа порядка 2
34 это не грозило бы конечно.
Михаил Орлов писал(а):Интересно, много ли операций такая арифметика поддерживает для универсальных Variant?
Так я же привёл в предыдущем посте
ссылку на страницу с перечислением всех операций из этой когорты:
- VarAbs — Returns the absolute value of a variant.
- VarAdd — Returns the sum of two variants.
- VarAnd — Performs a bitwise And operation between two variants of any integral type.
- VarCat — Concatenates two variants and returns the result.
- VarCmp — Compares two variants.
- VarDiv — Returns the result from dividing two variants.
- VarEqv — Performs a bitwise equivalence on two variants.
- VarFix — Returns the integer portion of a variant.
- VarIdiv — Converts two variants of any type to integers then returns the result from dividing them.
- VarImp — Performs a bitwise implication on two variants.
- VarInt — Returns the integer portion of a variant.
- VarMod — Divides two variants and returns only the remainder.
- VarMul — Returns the result from multiplying two variants.
- VarNeg — Performs logical negation on a variant.
- VarNot — Performs the bitwise not negation operation on a variant.
- VarOr — Performs a logical disjunction on two variants.
- VarPow — Returns the result of performing the power function with two variants.
- VarR4CmpR8 — Compares two variants of types float and double.
- VarR8Pow — Performs the power function for variants of type double.
- VarR8Round — Rounds a variant of type double to the specified number of decimal places.
- VarRound — Rounds a variant to the specified number of decimal places.
- VarSub — Subtracts two variants.
- VarXor — Performs a logical exclusion on two variants.
По сути это все VB-шные унарные и бинарные операторы (кроме Like), плюс псевдофункции Abs(), Int(), Fix().
Если я правильно понял, foo * foo и bar * bar посчитает OLEAUT32.DLL, затем - конверсия в Double, вычисляются Sin, Cos и "+", и, наконец, ещё один вызов OLEAUT32.DLL для записи резултата?
Тут нужно понимать, что в целом/идеологически у VBA есть собственные функции для осуществления всех операций с VARIANT-значениями: __vbaVarAbs, __vbaVarFix, __vbaVarAdd, __vbaVarSub, __vbaVarCat.
Псевдокодное воплощение VBA-кода имеет свои P-code-инструкции для работы с вариантом, которые вызывают эти __vbaVar
Xxxx-функции. При компиляции VB-проектов в Native-код прямо из кода вызываются соответствующие __vbaVarXxxx-функции.
Поэтому для подсчёта
foo * bar будет вызвана __vbaVarMul.
Для приведения типа
foo * bar из Variant в Double будет вызвана __vbaR8Var.
Подсчёт синуса и косинуса будут вызваны rtcSin/rtcCos.
Для приведения типа из Double в Variant после вызова триг. функций ничего не вызывается, это тривиальная задача.
Для осуществления операции присваивания Variant-а вызывается __vbaVarMove.
Это как бы общий случай.
Теперь частный случай: в версии VBA для Windows многих из этих функций (__vbaVar
Xxxxxx) не делают основную часть работы сами, а вызывают соответствующие функции из OLEAUT32.DLL. Например __vbaVarMul вызывает VarMul из OLEAUT32.DLL. Но это билды VBA для Windows. Хочется спросить: а что, существуют варианты сборки VBA не для Windows? Почти что нет, но хорошо известно, что существовали версии VBA (здесь VBA включает и VB, так как самостоятельный VB это Ruby+VBA) для Macintosh. В VBA есть функции MacID и MacScript даже для не-Macintosh-сборок.
Теоретичесик, было бы желание, из исходников VBA могли бы скомпилирвоать и версии VBA под какие-то другие платформы и операционные системы.
Не знаю, как в версии для Macintosh — не щупал, но в версии для Windows, как я уже сказал, многие из этих функций основную часть работы перекладывают на OLEAUT32.DLL. В версии для Mac, надо полагать, всю работу с вариантами VBA делает самостоятельно, ведь никакого OLEAUT32.DLL там нет.
Многие, как я сказал, но не все. И не всю работу.
__vbaVarMul например просто вызывает OLEAUT32!VarMul, а затем только проверает код возврата и «транслирует» его в исключение, если операция сбойнула. То есть это просто тривиальная обёртка.
А вот __vbaVarCat хоть и вызывает OLEAUT32!VarCat, делает очень много предварительных доп. действий сама. То есть это обёртка, но не тривиальная.
А вот __vbaVarMove не является просто обёрткой над какой-то функцией из OLEAUT32.DLL. То есть это вообще не обёртка над какой-то OLEAUT32-функцией.
__vbaR8Var тоже не пользуется услугами OLEAUT32.DLL, всё делает сама.
Но опять-таки, это актуально только для Windows-сборок VBA, хоть других можно сказать, что и нет (почти).
Так что «и, наконец, ещё один вызов OLEAUT32.DLL для записи резултата» — не правда.
Михаил Орлов писал(а):Или (вдруг) Sin и Cos тоже есть в OLEAUT32.DLL?
Нету, да и нет такой нужды. Для операций с вариантами такие функции есть только потому, что там огромное разнообразие опций относительного того, как можно (и нужно) действовать, когда входные операнды имеют разные типы. Например сложение числа и строки, числа и Null, числа и Empty. И главное, что правила приведений типов «к общему знаменателю» и обработки крайних случаев должны быть у всех програм одинаковые.
А синус — с ним всё просто. На входе Double, на выходе всегда Double. Никаких corner cases и никаки приведений типов.