Страницы: 1
RSS
Длинная арифметика, длинное число (LongNum) для VBA - .DLL / .XLL
 
Друзья, всем привет!
Для всех кто любит VBA, решил написать помощник в длинной арифметики.
Это продолжение и наверное завершение моих предыдущих трех тем.
Реализация через .XLL, т.е. все очень просто - устанавливается как надстройка и готово!
Длинное число с математикой работает как экземпляр объекта.
Перегрузка операторов в VBA - мечта, поэтому тупо через свойства и методы.
Скорость работы - более чем в 10 раз быстрее чем все предыдущие решения (!100000=20 сек, 1000000!='8,263931688331240E+5565708 - 50мин.)
Есть справка .Help:

Properties (Name-Type-Description)
1) L - as Object - LongNum
2) LNum - as Int32 - Converts the numeric value (Int32-Holds signed 32-bit (4-byte) integers that range in value from -2,147,483,648 through 2,147,483,647.).
3) LString(Optional format) - as String - Converts the String\Exponential notation (format = "E...", example:"E5"="1.11111E+...")
4) Sign - As Integer - Gets a number that indicates the sign (negative, positive, or zero) of the currentLongNum object.
5) IsEven - As Boolean - Indicates whether the value of the current LongNum object is an even number.
   
Methods (Name-Return-Description)
1) Addition(LongNum, LongNum, Optional Subtraction) - As LongNum - Adds/Subtracts two LongNum values and returns the result.
2) Copy(LongNum) - No - Specifies the LongNum to which the specified object will be copied
3) Compare(LongNum, LongNum) - As Integer - Compares two LongNum values and returns an integer that indicates whether the first value is less than, equal to, or greater than the second value.
4) Divide(LongNum, LongNum) - As LongNum - Divides one LongNum value by another and returns the result.
5) Factorial(Int32) - As LongNum - Returns a BigInteger value - Factorial of a specified value.
6) Help - Msgbox - Help
7) HelpString - As String - Help
8) Modulus(LongNum, LongNum) - As LongNum - Performs integer division on two LongNum values and returns the remainder.
9) Multiply(LongNum, LongNum) - As LongNum - Returns the product of two LongNum values.
10) Negate(LongNum) - As LongNum - Negates a specified LongNum value.
11) Pow(LongNum, Int32) - As LongNum - Raises a LongNum value to the power of a specified value.

Подключаем  .XLL. вносим код в обычный модуль, смотрим :)
Код
Option Explicit

Sub Test()
Dim LN As Object
Dim LN2 As Object

Set LN = CreateObject("LongNum")
Set LN2 = CreateObject("LongNum")
    
LN.LString = "4.564464545656464647E+45665" 'парсинг строки и строки в экспоненциальной записи в LongNum

'LN2.l = LN.l 'копия из LN в LN2 вариант1
LN.Copy LN2 'копия из LN в LN2 вариант2

LN2.LString = "65655654" 'парсинг строки и строки в экспоненциальной записи в LongNum
LN2.LNum = 65655654 'в числовом формате

'LN.l = LN.Multiply(LN, LN2) 'умножить вариант 1
Set LN = LN.Multiply(LN, LN2) 'умножить вариант 2

Debug.Print "Вывести: строка= " & LN.LString
Debug.Print "Вывести: в экспоненциальной записи= " & LN.LString("E5") 'E5 - 5 знаков в мантиссе, после запятой

Debug.Print Application.Run("Fact", 50) 'бонус :)

LN.Help 'Справка
Debug.Print LN.HelpString 'Справка в строке

StrPrint [a1], LN.LString

End Sub

Public Sub StrPrint(Cell As Range, ByVal s As String) 'вывести в ячейку/ки длинное число
Dim x As Long, l As Long
l = Len(s)
For x = 0 To l \ 32766
Cell.Offset(0, x) = "'" & Mid$(s, 32766 * x + 1, 32766)
Next
End Sub
Ввод: строка, экспоненциальной запись (с любой степенью), Long
Вывод: строка (обычная - по умолчанию, и экспоненциальная запись (с задаваемой мантиссой)
xll. не пролезают, залил на Яндекс диск:
Для Excelx32 - https://yadi.sk/d/iM8ElM7UtGXet
Для Excelx64 - https://yadi.sk/d/j2MCk4C_tGXez

Какие мнения?
«Бритва Оккама» или «Принцип Калашникова»?
 
Всем Привет! Было не легко, но оно того стоило!
Итак позволю себе нескромность)
Представляю вам новое (второе, .xll) мое решение для Excel (VBA), под названием "НАГИБАТЕЛЬ ВСЕЯ..."
Нагибает: все мои предыдущие проекты, длинную арифметику от Microsoft (BigInteger Structure), все проекты для Excel, которые я встречал (в т.ч. и на этом форуме).
Подозреваю, что это самая быстрая длинная арифметика для Excel, реализованное в одном файле/надстройке.

Для производительности изменил/сократил логику функций.
Все описание есть в .Help.

Михаил, специально для вас, порадуйтесь результату :
Код
Sub test_new()
    Dim lng As Object, t1 As Single, t2 As Single
    Set lng = CreateObject("LongNum")
    t1 = Timer
    lng.String = "9"
    Set lng = lng.Power(999999)
    Set lng = lng.Add(lng)
    t2 = Timer
    StrPrint [a1], lng.String
    Debug.Print t2 - t1, Timer - t2
End Sub
Public Sub StrPrint(Cell As Range, ByVal s As String) 
Dim x As Long, l As Long
l = Len(s)
For x = 0 To l \ 32766
Cell.Offset(0, x) = "'" & Mid$(s, 32766 * x + 1, 32766)
Next
End Sub


Файлы здесь, т.к. не пролезают.
«Бритва Оккама» или «Принцип Калашникова»?
 
Использование fullwords в качестве основного арифметического типа, ассемблер - это сила! Расчет факториала !1 000 000  - меньше 1 сек. (5 565 709 знаков)
«Бритва Оккама» или «Принцип Калашникова»?
 
Итак всем привет! Представляю вашему вниманию третий выпуск моего проекта.
Добавлено в LongNum:
1.Ввод и вывод строки с основанием от 2 до 36 (парсинг строки с бинарного в 16-е основание 1млн. знаков - 0,02 сек)
Код
Sub test()
    Dim LN As Object, t, x
    t = Timer
    Set LN = CreateObject("LongNum")
    LN.SetString "1" & String$(999999, "1"), 2
    StrPrint [a1], LN.GetString(16)
    Debug.Print Timer - t
End Sub
Public Sub StrPrint(Cell As Range, ByVal s As String) 
Dim x As Long, l As Long
l = Len(s)
For x = 0 To l \ 32766
Cell.Offset(0, x) = "'" & Mid$(s, 32766 * x + 1, 32766)
Next
End Sub

2.Ввод и вывод в байтовый массив (очень быстро)
3.Вычисление корня n-го корня, с выводом остатка! (до целого деления)
4.Много других приятностей
Полный список (прошу прощения за свой английский, исправления принимаю):
Скрытый текст


Добавлен новый тип! DoubleNum - число с плавающей точкой/запятой
Точность числа ограниченна только вашей оперативной памятью. Советую сразу задавать размер в битах через .SizeBits
Из-за особенностей числа функции имеют немного другой алгоритм чем в LongNum.
DoubleNum Class Reference на данный момент:
Скрытый текст


Исходники
Изменено: bedvit - 04.08.2016 20:29:21
«Бритва Оккама» или «Принцип Калашникова»?
 
Простенький пример использования двух типов чисел:
Код
Sub LongNum()
Dim LN As Object
Dim DN As Object
Set LN = CreateObject("LongNum")
Set DN = CreateObject("DoubleNum")
    
    LN.String = "12345678" & String$(100, "9") 'задаем длинное число LongNum
    Set LN = LN.Add(LN)   'суммируем LongNum
    
    DN.SizeBits = 128     'задаем размер в битах (длина мантиссы) DoubleNum
    DN.String = LN.String 'передаем значение в DoubleNum (пока через строку)
    DN.Add DN, DN         'суммируем DoubleNum
    DN.Root DN            'вычисляем корень в DoubleNum из DoubleNum
    Debug.Print DN.String 'выводим значение DoubleNum
 
'При DN.SizeBits = 64, результат "0.702728368574942333671e+54"
'При DN.SizeBits = 128, результат "0.7027283685749423336709820379365737758043e+54"
 
LN.Help 'Справка
End Sub
Изменено: bedvit - 18.08.2016 12:11:22
«Бритва Оккама» или «Принцип Калашникова»?
 
Версия 0.0.0.5:
1. Создан механизм проверки правильного парсинга String (Scientific notation, Decimal notation) для DoubleNum
2. Оптимизированы некоторые функции
3. Добавлен вывод DoubleNum как в дробном виде (с точкой), так и в экспоненциальной записи.
4. Добавлено несколько новых функций
5. Оптимизирован размер для библиотеки х64.

Пока не сделано:
1.Переполнение по exponent библиотекой сейчас НЕ ПРОВЕРЯЕТСЯ (значения в рамках: от-2,147,483,648 до 2,147,483,647)
2.RationalNum Class

Версия 0.0.0.5 (последние версии всегда здесь)

Параллельное обсуждение данной темы.
Изменено: bedvit - 14.09.2016 15:36:57
«Бритва Оккама» или «Принцип Калашникова»?
Страницы: 1
Читают тему
Наверх