Друзья, всем привет! Для всех кто любит 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.Много других приятностей Полный список (прошу прощения за свой английский, исправления принимаю):
Скрытый текст
LongNum Class Reference
Properties (Name-Type-Description)
1) L - as Object - LongNum
2) Num - 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) String - as String - Parsung/Converts the String
4) Even - as Int32 - Determine whether LongNum is odd or even, respectively. Return non-zero if yes, zero if no.
5) Sign - As Int32 - Sign LongNum
Methods (Name-Return-Description)
1) Abs() - As LongNum - Returns a new*LongNum*which is the absolute value of this value.
2) Add(LongNum) - As LongNum - Add LongNum*value to the this LongNum*valuesand returns the result.
3) Add2(Int32) - As LongNum - Add integer*value to the this LongNum*value and returns the result.
4) Clone() - As LongNum - Returns a clone this LongNum
Cmp(LongNum) - as Int32 - Compare LongNum1 and LongNum2. Return a positive value if this*LongNum > set*LongNum, zero if this*LongNum > set*LongNum, or a negative value if this*LongNum < set*LongNum
6) Copy(LongNum) - No - Specifies the LongNum to which the specified object will be copied
7) Divide(LongNum) - As LongNum - Divides one*LongNum*value by another and returns the result.
Divide2(Int32) - As LongNum - Divides one*LongNum*value by integer*value and returns the result.
9) Factorial(Int32) - As LongNum - Factorial of a specified value.
10) Fibonacci(int32) - As LongNum - Fibonacci number
11) GetByteArray(optional Int32 order=-1) - As byte[](unsigned) - Endianess is specified by order, which is 1 for big endian or -1 for little endian
12) GetString(optional uint Base = 10) - as String - Convert LongNum to a string of digits in base base. The base may vary from 2 to 36 or from -2 to -36. For base in the range 2..36, digits and lower-case letters are used; for -2..-36, digits and upper-case letters are used.
13) Help() - As System.Windows.Forms - LongNum Class Reference
14) LucNum(UInt32) - As LongNum - Lucas number
15) Mod(LongNum) - As LongNum - Performs integer division on two*LongNum*values and returns the remainder.
16) Mod2(UInt32) - As LongNum - Performs integer division LongNum on integer*value and returns the remainder.
17) Multiply(LongNum) - As LongNum - Returns the product of two*LongNum*values.
18) Multiply2(Int32) - As LongNum - Returns the product of LongNum*value and integer*value
19) Negate() - As LongNum - Negates a this*LongNum*value and returns the result.
20) Power(Int32) - As LongNum - Raises a*LongNum*value to the power of a specified value.
21) RootRem(uint n, LongNum remainder) - As LongNum - - As LongNum - Return root and remainder this*LongNum (n - is the degree of the root, remainder as LongNum - remainder)
22) SetByteArray(byte[](unsigned), optional Int32 order=-1) - No - Endianess is specified by order, which is 1 for big endian or -1 for little endian (unsigned)
23) SetString(string Str, optional uint Base = 10) - No - Set the value of LongNum from str, a null-terminated C string in base base. White space is allowed in the string, and is simply ignored. The base may vary from 2 to 36 or from -2 to -36. For base in the range 2..36, digits and lower-case letters are used; for -2..-36, digits and upper-case letters are used.
24) Subtract(LongNum) - As LongNum - Subtracts one LongNum value from another and returns the result.
25) Subtract2(Int32) - As LongNum - Subtracts integer*value from the this LongNum*value and returns the result.
Добавлен новый тип! DoubleNum - число с плавающей точкой/запятой Точность числа ограниченна только вашей оперативной памятью. Советую сразу задавать размер в битах через .SizeBits Из-за особенностей числа функции имеют немного другой алгоритм чем в LongNum. DoubleNum Class Reference на данный момент:
Скрытый текст
DoubleNum Class Reference
Properties (Name-Type-Description)
1) D - as Object - DoubleNum
2) Num - as Double- Converts the numeric value (double-The double keyword signifies a simple type that stores 64-bit floating-point values. ±5.0 × 10−324 to ±1.7 × 10+308).
3) String - as String - Parsung/Converts the String
4) SizeBits - as Ulong - Set/Get the current precision of DoubleNum, in bits.
Methods (Name-Return-Description)
1) Abs(DoubleNum) - No - Returns in this*DoubleNum*which is the absolute value of set value.
2) Add(DoubleNum, DoubleNum) -No - Add DoubleNum*value to the set DoubleNum*valuesand returns the result in this*DoubleNum*
3) Cmp(DoubleNum) - as Int32 - Compare DoubleNum1 and DoubleNum2. Return a positive value if this*DoubleNum > set*DoubleNum, zero if this*DoubleNum > set*DoubleNum, or a negative value if this*DoubleNum < set*DoubleNum
4) Copy(DoubleNum) - No - Specifies the DoubleNum to which the specified object will be copied
5) Divide(DoubleNum, DoubleNum) - No - Divides one*DoubleNum*value by another and returns the result in this*DoubleNum*
6) GetString(Base, n_digits) - as String - Convert DoubleNum to a string of digits in base base. The base may vary from 2 to 36 or from -2 to -36. For base in the range 2..36, digits and lower-case letters are used; for -2..-36, digits and upper-case letters are used. n_digits - number of digits
7) Help() - As System.Windows.Forms - DoubleNum Class Reference
Multiply(DoubleNum, DoubleNum) - No - Returns the product of two*DoubleNum*values in this*DoubleNum*
9) Negate(DoubleNum) - No - Negates a set*DoubleNum*value and returns the result in this*DoubleNum*
11) SetString(String, Base ) - No - Set the value of DoubleNum from str, a null-terminated C string in base base. White space is allowed in the string, and is simply ignored. The base may vary from 2 to 36 or from -2 to -36. For base in the range 2..36, digits and lower-case letters are used; for -2..-36, digits and upper-case letters are used.
12) Subtract(DoubleNum, DoubleNum) - No - Subtracts one DoubleNum value from another and returns the result in this*DoubleNum*
Простенький пример использования двух типов чисел:
Код
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
Версия 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