Длинная арифметика (Bignum arithmetic) c COM-интерфейсом и C API Functions для Excel на библиотеках MPIR. С/С++
Запись от bedvit размещена 26.03.2018 в 22:15
Показов 26512
Комментарии 160
|
Теперь часть библиотеки BedvitCOM. Проект основан на исходниках (на С++) библиотеки MPIR, Edition 3.0.0. (на основе библиотеки GMP) Полностью написан на С/С++. Скорость на порядок выше предыдущего решения. Реализовал два блока в проекте: 1.DLL c COM интерфейсом. Реализованы dual-интерфейсы с Automation-совместимыми типами данных, структур (поддержка как раннего вывязывания, так и позднего). Ранний предпочтительнее в части скорости (на 50% быстрее передача данных через СОМ-обертку). Реализовано два класса: класс целых чисел с арифметикой (BignumArithmeticInteger) и класс чисел с плавающей точкой (BignumArithmeticFloat). При создании экземпляра класса создается массив К числам можно обращаться по индексам (можно переменной присвоить индекс и работать с переменными, см. пример ниже) BignumArithmeticInteger (Bignum) увеличивается в памяти по мере расчета автоматически, перераспределяя память. BignumArithmeticFloat (Bignum), задается изначально, т.к. дробь может быть бесконечной (по умолчанию принимается минимальный размер - double). Размер чисел ничем не ограничен, кроме вашей оперативки. Регистрация COM реализовано как под админом, так и под пользователем (актуально в офисной части клиентов) Регистрация стандартная: Админ: Regsvr32 "FullName.DLL" !ПОМНИМ! В Win10 регистрация под правами админа: "правая кнопка" - "Пуск" -"Командная строка (администратор)" Пользователь: Regsvr32 /i /n "FullName.DLL" Удалить из реестра: Regsvr32 /u "FullName.DLL" Свойства и методы последней версии библиотеки COM (из .Help): Свойства и Методы BignumArithmeticInteger 1.Help(); HTML Справка (без параметров). 2.BSTR* StringBSTR = Bignum(BYTE Bignum, LONG BignumBase=10) = BSTR* StringBSTR ; Свойство. Принимает и возвращает BSTR* строку StringBSTR (задает число или возвращает значение). Bignum-индекс длинного числа в массиве (0-255). BignumBase-база длинного числа (от 2 до 36), по умолчанию = 10. 3.LONG Val = Sign(BYTE Bignum); Свойство. Возвращает знак длинного числа LONG Val.Возвращает 1 если Bignum > 0, 0 если Bignum = 0, и -1 если Bignum < 0. 4.LONG Val = Even(BYTE Bignum); Свойство. Определяет, является ли Bignum четное или нечетное. Возвращает 1 - Bignum четное, 0 - Bignum нечетное. 5.LONG Val = Compare(BYTE Bignum1, BYTE Bignum2); Метод. Сравнивает два длинных числа. Возвращает 1 если Bignum1 > Bignum2, 0 если Bignum1 = Bignum2, и -1 если Bignum1 < Bignum2. 6.BignumSet(BYTE Bignum, BSTR StringBSTR, LONG BignumBase=10); Метод. Задает число с параметрами аналогичными свойству Bignum() 7.Sum(BYTE BignumSet, BYTE Bignum1, BYTE Bignum2); Метод. Суммирует два длинных числа. BignumSet = Bignum1 + Bignum2 8.SumL(BYTE BignumSet, BYTE Bignum1, LONG_PTR LONG_PTR); Метод. Суммирует длинное число с обычным. BignumSet = Bignum1 + LONG_PTR(х64:LONG_PTR= LONGLONG, х32:LONG_PTR= LONG) 9.Abs(BYTE BignumSet, BYTE Bignum1); Метод. Возвращает модуль значения из Bignum1 в BignumSet. 10.Negate(BYTE BignumSet, BYTE Bignum1); Метод. Возвращает значение с противоположным знаком из Bignum1 в BignumSet. BignumSet = - Bignum1. 11.Subtract(BYTE BignumSet, BYTE Bignum1, BYTE Bignum2); Метод. Вычитает из одного длинного числа второе. BignumSet = Bignum1 - Bignum2 12.SubtractL(BYTE BignumSet, BYTE Bignum1, LONG_PTR LONG_PTR); Метод. Вычитает из длинного числа обычное. BignumSet = Bignum1 - LONG_PTR. 13.Multiply(BYTE BignumSet, BYTE Bignum1, BYTE Bignum2); Метод. Умножает одно длинное число на второе. BignumSet = Bignum1 * Bignum2. 14.MultiplyL(BYTE BignumSet, BYTE Bignum1, LONG_PTR LONG_PTR); Метод. Умножает длинное число на обычное. BignumSet = Bignum1 * LONG_PTR. 15.Divide(BYTE BignumQuotient, BYTE BignumRemainder, BYTE Bignum1, BYTE Bignum2); Метод. Делит одно длинное число на второе. При делении получаем частное в BignumQuotient, остаток от деления в BignumRemainder = Bignum1 / Bignum2. 16.DivideL(BYTE BignumQuotient, BYTE BignumRemainder, BYTE Bignum1, LONG_PTR LONG_PTR); Метод. Делит длинное число на обычное. При делении получаем частное в BignumQuotient, остаток от деления в BignumRemainder = Bignum1 / LONG_PTR. 17.Power(BYTE BignumSet, BYTE Bignum1, LONG_PTR LONG_PTR); Метод. Возводит в степень LONG_PTR длинное число Bignum1, результат возвращает в BignumSet. BignumSet = Bignum1 ^ LONG_PTR. 18.Clone(BYTE BignumSet, BYTE Bignum1); Метод. Копирует Bignum1 в BignumSet. BignumSet = Bignum1 19.RootRem(BYTE BignumRoot, BYTE BignumRemainder, BYTE Bignum1, LONG_PTR n_root); Метод. Извлекает корень n_root-степени из Bignum1. Целочисленный результат возвращает в BignumRoot, остаток в BignumRemainder = (n-th root)√ Bignum1. 20.Factorial(BYTE BignumSet, LONG n); Метод. Возвращает в BignumSet факториал n! 21.Fibonacci(BYTE BignumSet, LONG_PTR n); Метод. Возвращает в BignumSet число Фибоначи n. Fn+1 = Fn + Fn-1 22.LucNum(BYTE BignumSet, LONG_PTR n); Метод. Возвращает в BignumSet число Лукоса n. Ln+1 =Ln + Ln-1 23.FileSet(BYTE Bignum, BSTR StringBSTRFileName, LONG BignumBase=10); Метод. Загружает длинное число из файла (*.txt). Принимает BSTR* строку StringBSTRFileName в качестве полного пути и имени файла. Bignum-индекс длинного числа в массиве (0-255). BignumBase-база числа (от 2 до 36), по умолчанию = 10. 24.FileGet(BYTE Bignum, BSTR StringBSTRFileName, LONG BignumBase=10); Метод. Сохраняет длинное число в файл (*.txt). Принимает BSTR* строку StringBSTRFileName в качестве полного пути и имени файла. Bignum-индекс длинного числа в массиве (0-255). BignumBase-база числа (от 2 до 36), по умолчанию = 10. 25.Clear(LONG Bignum=-1); Метод. Освобождает память занятую длинным числом Bignum, или освобождает память занятую всеми числами при заданном параметре по умолчанию = -1. 26.LONG Val = BignumArraySize(); Метод. Возвращает количество чисел Bignum в созданном классе/массиве. Начиная с v2.0.0.0 (теперь массив чисел может быть произвольного размера, а не как ранее 256 чисел. Размер увеличиваться автоматически.) Свойства и Методы BignumArithmeticFloat 1.Help(); HTML Справка (без параметров). 2.LONG Val = SizeBits(BYTE Bignum, LONG_PTR* pVal) = .LONG Val; Свойство. Задает и возвращает размер длинного числа в БИТАХ LONG Val. Bignum-индекс длинного числа в массиве (0-255). 3.BSTR* String = Bignum(BYTE Bignum, LONG BignumBase=10, LONG_PTR Precision=0, BSTR Separator=”.”, VARIANT_BOOL Exponential=-1) = BSTR* String; Свойство. Принимает и возвращает BSTR* строку String (задает число или возвращает значение). Bignum-индекс длинного числа в массиве (0-255). BignumBase-база длинного числа (от 2 до 36), по умолчанию = 10. Precision – точность (кол-во цифр в числе), по умолчанию = 0 - максимальная (равна заданному размеру в битах). Separator – символ разделителя целой и дробной частей числа, по умолчанию точка(“.”). Exponential – по умолчанию =-1 экспоненциальная запись, 0 – десятичная (в разработке). (При парсинге строки в число, ожидаемая десятичная точка берется из текущей локали, на системах, предоставляющих localeconv). 4.LONG Val = Sign(BYTE Bignum); Свойство. Возвращает знак длинного числа LONG Val.Возвращает 1 если Bignum > 0, 0 если Bignum = 0, и -1 если Bignum < 0. 5.LONG Val = Compare(BYTE Bignum1, BYTE Bignum2); Метод. Сравнивает два длинных числа. Возвращает 1 если Bignum1 > Bignum2, 0 если Bignum1 = Bignum2, и -1 если Bignum1 < Bignum2. 6.SizeBitsSet(BYTE Bignum, LONG_PTR SizeBits); Метод. Задает размер длинного числа в БИТАХ LONG Val. 7.BignumSet(BYTE Bignum, BSTR StringBSTR, LONG BignumBase=10, BSTR Separator=”.”); Метод. Задает число с параметрами аналогичными свойству Bignum(). 8.Sum(BYTE BignumSet, BYTE Bignum1, BYTE Bignum2); Метод. Суммирует два длинных числа. BignumSet = Bignum1 + Bignum2 9.SumL(BYTE BignumSet, BYTE Bignum1, LONG_PTR LONG_PTR); Метод. Суммирует длинное число с обычным. BignumSet = Bignum1 + LONG_PTR(х64:LONG_PTR= LONGLONG, х32:LONG_PTR= LONG) 10.Abs(BYTE BignumSet, BYTE Bignum1); Метод. Возвращает модуль значения из Bignum1 в BignumSet. 11.Subtract(BYTE BignumSet, BYTE Bignum1, BYTE Bignum2); Метод. Вычитает из одного длинного числа второе. BignumSet = Bignum1 - Bignum2. 12.SubtractL(BYTE BignumSet, BYTE Bignum1, LONG_PTR LONG_PTR); Метод. Вычитает из длинного числа обычное. BignumSet = Bignum1 - LONG_PTR. 13.Multiply(BYTE BignumSet, BYTE Bignum1, BYTE Bignum2); Метод. Умножает одно длинное число на второе. BignumSet = Bignum1 * Bignum2. 14.MultiplyL(BYTE BignumSet, BYTE Bignum1, LONG_PTR LONG_PTR); Метод. Умножает длинное число на обычное. BignumSet = Bignum1 * LONG_PTR. 15.Divide(BYTE BignumSet, BYTE Bignum1, BYTE Bignum2); Метод. Делит одно длинное число на второе. BignumSet = Bignum1 / Bignum2 16.DivideL(BYTE BignumSet, BYTE Bignum1, LONG_PTR LONG_PTR); Метод. Делит длинное число на обычное. BignumSet = Bignum1 / LONG_PTR. 17.Root(BYTE BignumSet, BYTE Bignum1); Метод. Извлекает квадратный корень из Bignum1. Результат возвращает в BignumSet. BignumSet = √ Bignum1. 18.Negate(BYTE BignumSet, BYTE Bignum1); Метод. Возвращает значение с противоположным знаком из Bignum1 в BignumSet. BignumSet = - Bignum1. 19.Power(BYTE BignumSet, BYTE Bignum1, LONG_PTR LONG_PTR); Метод. Возводит в степень LONG_PTR длинное число Bignum1, результат возвращает в BignumSet. BignumSet = Bignum1 ^ LONG_PTR. 20.Clone(BYTE BignumSet, BYTE Bignum1); Метод. Копирует Bignum1 в BignumSet. BignumSet = Bignum1 21.FileSet(BYTE Bignum, BSTR StringBSTRFileName, LONG BignumBase=10); Метод. Загружает длинное число из файла (*.txt). Принимает BSTR* строку StringBSTRFileName в качестве полного пути и имени файла. Bignum-индекс длинного числа в массиве (0-255). BignumBase-база числа (от 2 до 36), по умолчанию = 10. (При парсинге строки в число, ожидаемая десятичная точка берется из текущей локали, на системах, предоставляющих localeconv). 22.FileGet(BYTE Bignum, BSTR StringBSTRFileName, LONG BignumBase=10, LONG_PTR Precision=0); Метод. Сохраняет длинное число в файл (*.txt). Принимает BSTR* строку StringBSTRFileName в качестве полного пути и имени файла. Bignum-индекс длинного числа в массиве (0-255). BignumBase-база числа (от 2 до 36), по умолчанию = 10. Precision – точность (кол-во цифр в числе), по умолчанию = 0 - максимальная (равна заданному размеру в битах). 23.Clear(LONG Bignum=-1); Метод. Освобождает память занятую длинным числом Bignum, или освобождает память занятую всеми числами при заданном параметре по умолчанию = -1 24.LONG Val = BignumArraySize(); Метод. Возвращает количество чисел Bignum в созданном классе/массиве. Начиная с v2.0.0.0 (теперь массив чисел может быть произвольного размера, а не как ранее 256 чисел. Размер увеличиваться автоматически.) 25.BSTR* String = GetToBignumInt(LONG Bignum, LONG BignumBase=10); Метод. Преобразовать Bignum из Float в Integer и вывести. ВАЖНО! преобразование происходит с заданной ранее точностью в битах для Float (SizeBitsSet). Без округлений, отбрасывается дробная часть. Будьте внимательнее в таких преобразованиях. Начиная с v2.0.0.0. 2.XLL для Excel с C API функциями. Добавил базовый набор. Будет потребность в дополнительных - добавлю по запросу. Для функций создано два раздела в стандартном списке с названиями классов в COM (+один общий). Функции поддерживают многопоточные расчеты. Работа с функциями как с обычными (различий нет). Обычные написаны тоже на С/С++ под C API. Список C API - функций в Excel: 1.BedvitXLLBignumArithmeticInteger - функции для работы с длинными целыми числами. Функции: 1.1 SumInteger() - сложение двух длинных/обычных целых чисел 1.2 SubtractInteger() - вычитание двух длинных/обычных целых чисел 1.3 MultiplyInteger() - умножение двух длинных/обычных целых чисел 1.4 DivideInteger() - деление двух длинных/обычных целых чисел - Неполное частное 1.5 ModInteger() - деление двух длинных/обычных целых чисел - Остаток от деления 1.6 PowerInteger() - возведение в степень длинного/обычного целого числа 1.7 ConvertBaseInteger() - конвертирование целого числа (строки) из одной базы в другую (от 2 до 36). 1.8 FactorialInteger() - факториал задаваемого числа. 2.XLLBignumArithmeticFloat - функции для работы с длинными дробными числами. Функции: 2.1 SumFloat() - сложение двух длинных/обычных чисел с плавающей точкой 2.2 SubtractFloat() - вычитание двух длинных/обычных чисел с плавающей точкой 2.3 MultiplyFloat() - умножение двух длинных/обычных чисел с плавающей точкой 2.4 DivideFloat() - деление двух длинных/обычных чисел с плавающей точкой 2.5 PowerFloat() - возведение в степень длинного/обычного числа 2.6 RootFloat() - извлечение квадратного корня из длинного/обычного числа Так же в XLL ресурсы упакована COM.DLL (первый блок проекта), распаковывается и устанавливается под пользователем - автоматом. Поэтому открываем XLL или устанавливаем как надстройку - готово (ничего регистрировать не надо). Пишем код в VBA и работаем. Советую раннее связывание. Видим свойства и методы объекта. Оные можно посмотреть и в диспетчере объектов (см. рис.) Т.е. при открытии XLL можно работать как с новыми C API функциями, так и с COM.DLL через VBA. Примеры см. ниже. Ресурсы: MPIR library, Edition 3.0.0 (freely distributable librarys) http://mpir.org/ + my code written in C / C ++ ©2018, BedvitCOM, BedvitXLL License: Freely distributable library Где тестировалось: Пример №1 (Расширенный): VBA - через индексы, раннее+позднее связывание:
Пример №3 (Простой): VBA - через буквенное обозначение, позднее связывание
Пример №4: 1С - через буквенное обозначение
26/03/2018 - Версия 0.0.0.1 под x64. 05/04/2018 - Новая версия BedvitCOM v.1.0.0.2 и BedvitXLL v.1.0.0.2 Изменения: 1. Изменен порядок аргументов в методе "BignumSet" (теперь, как во всех других методах, номер длинного числа в массиве - стоит первым аргументом), см.под спойлером Кликните здесь для просмотра всего текста
Ранее было так:
I.BignumSet "6546414654564" , 1 теперь так: I.BignumSet 1, "6546414654564" 2. Добавлены новые методы в два класса (запись длинного числа в файл .txt и чтение из файла) .FileSet, .FileGet (описание в .Help и ниже) 3. Собраны библиотеки COM и XLL в 32-разрядной версии (с корректным Help-ом, описанием интерфейса). 24/04/2018 - Новая версия BedvitCOM v.1.0.0.3 и BedvitXLL v.1.0.0.3 (поддержка х32 и х64) 1. Добавлены новые функции в два класса библиотеки COM - арифметика длинных чисел с обычными, т.е. теперь можно совершать арифметические действия длинных чисел с обычными. 2. Добавлен механизм очистки/освобождения памяти как для одного числа, так и для класса/объекта в целом. 3. Сделано новое описание для всех свойств и методов двух классов на русском языке в справке (см. под спойлером и в .HELP) 4. XLL теперь удаляет данные из реестра (COM.DLL) под пользователем при закрытии надстройки. 29/04/2022 - Новая версия BedvitCOM v.2.0.0.0 1.Класс/массив Bignum теперь может быть любого размера, а не как ранее 256 чисел. Увеличение размера происходит автоматом, в зависимости от последнего задаваемого индекса числа в массиве. 2.В связи с этим добавлен метод BignumArraySize() - Возвращает количество чисел Bignum в созданном классе/массиве. 3.Добавлено преобразование Bignum из Float в Integer (обратное преобразование было возможно и ранее). Метод GetToBignumInt(LONG Bignum, LONG BignumBase=10). ВАЖНО! преобразование происходит с заданной ранее точностью в битах для Float (SizeBitsSet). Без округлений, отбрасывается дробная часть. Будьте внимательнее в таких преобразованиях. 4.Исправлен баг в выделением памяти для разных экземпляров одного и того же класса. Теперь для каждого экземпляра - свой участок памяти. 5.Теперь деструктор класса сам очищает память (при удалении класса или завершении процедуры в VBA). Методы Clear теперь нужны только там, где нужно освободить память в действующим классе. При завершении процедуры их писать не обязательно (для VB, и для языков, где класс уничтожается при завершении процедуры - запуская деструктор). | ||||||||||||||||||||
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 160
Комментарии
-
Запись от Avazart размещена 02.04.2018 в 23:35
-
Запись от bedvit размещена 03.04.2018 в 08:59
-
Она COM потому что под Windows. Если бы изначально здесь она позиционировала себя как кроссплатформенная, тогда был бы другой разговор, но опять-таки ничего не мешает сделать ее COM и использовать на других платформах, просто потеряв те фичи которые предоставляет Windows под COM.
Сообщение от Avazart
Вопросы в другом:
Чем лучше и чем проще? Я приводил код на ассемблере, чем проще не-COM метод? Зато с COM мы получаем полную поддержку со стороны скриптовых языков типа vbs, 1С и т.д.
А как тоже самое сделать для vbs или js?
Каких прослоек? Чем отличается вызов метода от вызова экспортируемой функции?Запись от The trick размещена 03.04.2018 в 09:25
-
Запись от Avazart размещена 03.04.2018 в 11:44
-
Запись от Avazart размещена 03.04.2018 в 11:49
-
Не вижу тогда преимуществ, в python также я думаю можно работать с COM.
Сообщение от Avazart
Какую прослойку? Что такое COM-прослойка? Вызов метода COM объекта это вызов функции по указателю. Какая разница вызывать функцию так или же посредством импорта?
Это ко мне вопрос? Я не знаю, это же не я разработчик этой библиотеки. Второй момент, каким образом сделать ее кроссплатформенной чтобы покрыть тот-же набор клиентских продуктов?
Ну так какая разница, все равно нужно делать несколько билдов под разные платформы. В текущем виде также можно сделать несколько билдов которые будут предоставлять COM объект, точнее уже сейчас он предоставляется через те же самые экспортируемые функции. Сама COM технология платформо-независима, ее можно реализовать хоть на микроконтроллере:
Запись от The trick размещена 03.04.2018 в 12:15
-
Запись от Avazart размещена 03.04.2018 в 12:29
-
Мы говорим о том что можно работать, а не о том что не нужно. Можно работать - плюс, нельзя (как в случае vbs/js) - минус. Пока плюсов больше у COM.
Сообщение от Avazart
Хорошо, что в технологии COM является платформо-зависимым? Т.е. к примеру у меня есть COM объект, какие сложности в работе с этим COM объектом возникнут например в Linux?Запись от The trick размещена 03.04.2018 в 12:44
-
Нет, я об этом и написал:
Запись от The trick размещена 03.04.2018 в 12:45
-
Запись от Avazart размещена 03.04.2018 в 12:49
-
Где больше-то? Пока больше у варианта с COM.
Сообщение от Avazart
Не знаю, я не пишу на js, но на vbs часто. Все-таки наверное лучше когда можно использовать дополнительный язык, не так ли? С COM мы можем как минимум vbs/js/1C использовать. Для чего был приведен в пример python я не знаю, в нем также можно использовать COM.
Сообщение от Avazart
Как можно не зная технологию что-то утверждать? Специально скинул на ассемблере листинг, чтобы посмотреть как детально это работает. Да даже просто логически подумать что намного лучше иметь указатель на нужные функции и их вызывать вместо того чтобы импортировать кучу функций получая тот же результат.
Сообщение от Avazart
Запись от The trick размещена 03.04.2018 в 13:15
-
+ VBA, где подключается одной строкой CreateObject(), и никаких обвязок делать не надо.
Сообщение от The trick
+ многие не настолько прокачены (в т.ч. и автор этих строк), как Вы, уважаемые коллеги, и вряд ли кто-то будет делать обвязку самостоятельно. Сейчас все хотят решение из коробки - открыть, работать. С этими целями и делался продукт + максимальный охват разных языков. Те, кто пишет на С/С++/C# могут сами подключить GMP/MPIR и пользоваться.Запись от bedvit размещена 03.04.2018 в 15:00
-
Запись от Avazart размещена 03.04.2018 в 20:42
-
Запись от Avazart размещена 03.04.2018 в 20:45
-
Запись от bedvit размещена 03.04.2018 в 21:19
-
Не выпадают.
Сообщение от Avazart
Запись от The trick размещена 03.04.2018 в 22:26
-
Запись от Avazart размещена 03.04.2018 в 23:05
-
Ну когда билд под Linux будет тогда я непременно покажу как это сделать. Мне не составит труда вызвать функцию по указателю, несмотря на то что я никогда не кодил под Linux.
Сообщение от Avazart
Запись от The trick размещена 03.04.2018 в 23:23
-
На С++ вы можете спокойно подключать GMP и пользоваться. Эта библа дополнение, а не замена к оригинальной библиотеке. Сколько обычных клиентов сидят на win, сколько на других ОС и пользуются не С\С++\С#(net сейчас заходит на другие платформы(?)). О каких процентах мы говорим? значимы ли они, в свете существования оригинальной библы.
Сообщение от Avazart
Запись от bedvit размещена 04.04.2018 в 08:43
-
Ничто не помешает использовать данную COM библиотеку на других платформах.
Сообщение от bedvit
Запись от The trick размещена 04.04.2018 в 19:50


