Форум программистов, компьютерный форум, киберфорум
Наши страницы
bedvit
Войти
Регистрация
Восстановить пароль
Оценить эту запись

Длинная арифметика для Excel (vba) через .XLL (C#.NET, неуправляемый код)

Запись от bedvit размещена 11.08.2016 в 11:36
Обновил(-а) bedvit 31.03.2017 в 21:55 (Новая версия продукта)

Друзья, всем привет!
Для всех кто любит VBA, решил написать помощник в длинной арифметики.
Реализация через .XLL, т.е. все очень просто - устанавливается как надстройка и готово!
Или просто запускается двойным кликом.
Длинное число с математикой работает как экземпляр объекта.
Перегрузка операторов в VBA - мечта, поэтому тупо через свойства и методы.
Упор был сделан на скорость работы, к примеру факториал миллиона !1000000='8,263931688331240E+5565708 -расчет меньше 1 сек.)
Есть справка .Help

В проекте использовался собственный код и свободно-распространяемые продукты:
Mpir.NET - http://wezeku.github.io/Mpir.NET/ (с библиотеками Mpir)
Excel - DNA*- https://excel-dna.net/ (http://exceldna.codeplex.com/)
Costura - https://github.com/Fody/Costura

Длинные числа, типы:
1. LongNum: целое число со знаком;
2. DoubleNum: число с плавающей точкой (задаваемая точность мантиссы).
3. RationalNum: в разработке - рациональное (частное от деления двух целых чисел);

Размер LongNum задается автоматически и растет в памяти по мере необходимости. Чтобы избежать частых перераспределений в памяти - перераспределяется только в сторону увеличения. DoubleNum использует предварительно задаваемый пользователем размер в битах, до нужной точности мантисы. Размер такой переменной - не меняется. Максимальный размер данных чисел зависит только от размера вашей оперативной памяти.

!Внимание: показатель степени(exponent) в DoubleNum на данный момент - это Int32(C#.NET) или Long (VBA), т.е. значения в рамках: от-2,147,483,648 до 2,147,483,647. Переполнение по exponent библиотекой сейчас НЕ ПРОВЕРЯЕТСЯ! Будьте внимательны в расчетах, и следите за переполнением (overflow).

Последняя версия на данный момент - 0.0.0.5
Продукт распространяется по свободной лицензии (автор конечного продукта и автор сего блога ©bedvit).

Содержание (.HELP):
LongNum Class Reference
Кликните здесь для просмотра всего текста
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

5) 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: quotient. (Integer division)

8) Divide2(Int32) - As LongNum - Divides one*LongNum*value by integer*value and returns the result: quotient. (Integer division)

9) DivideRem(LongNum, out LongNum remainder) - As LongNum - Divides one*LongNum*value by another and returns the result: quotient+remainder. (Integer division+remainder)

10) DivideRem2(Int32, out LongNum remainder) - As LongNum - Divides one*LongNum*value by integer*value and returns the result: quotient+remainder. (Integer division+remainder)

11) Factorial(Int32) - As LongNum - Factorial of a specified value.

12) Fibonacci(Int32) - As LongNum - Fibonacci number

13) GetByteArray(Int32 order=-1((optional )) - As byte[](unsigned) - Endianess is specified by order, which is 1 for big endian or -1 for little endian

14) GetString(Uint Base = 10((optional )) - 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.

15) Help() - As System.Windows.Forms - LongNum Class Reference

16) LucNum(UInt32) - As LongNum - Lucas number

17) Mod(LongNum) - As LongNum - Performs integer division on two*LongNum*values and returns the remainder.

18) Mod2(UInt32) - As LongNum - Performs integer division LongNum on integer*value and returns the remainder.

19) Multiply(LongNum) - As LongNum - Returns the product of two*LongNum*values.

20) Multiply2(Int32) - As LongNum - Returns the product of LongNum*value and integer*value

21) Negate() - As LongNum - Negates a this*LongNum*value and returns the result.

22) Power(Int32) - As LongNum - Raises a*LongNum*value to the power of a specified value.

23) RootRem(Uint n, LongNum remainder(out)) - As LongNum - - As LongNum - Return root and remainder this*LongNum (n - is the degree of the root, remainder as LongNum - remainder)

24) SetByteArray(Byte[](unsigned), Int32 order=-1(optional)) - No - Endianess is specified by order, which is 1 for big endian or -1 for little endian (unsigned)

25) SetString(String Str, Uint Base = 10(optional)) - 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.

26) Subtract(LongNum) - As LongNum - Subtracts one LongNum value from another and returns the result.

27) Subtract2(Int32) - As LongNum - Subtracts integer*value from the this LongNum*value and returns the result.

DoubleNum Class Reference
Кликните здесь для просмотра всего текста
DoubleNum Class Reference

!!! Note however DoubleNum.GetString can only return an exponent which fits an Int32 and currently DoubleNum.SetString doesn’t accept exponents bigger than a Int32 (Int32-Holds signed 32-bit (4-byte) integers that range in value from -2,147,483,648 through 2,147,483,647)
!!!No check for overflow the exponent !!!
DoubleNum functions and variables have no special notion of infinity or not-a-number, and applications must take care not to overflow the exponent or results will be unpredictable. !!!


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 (Scientific notation, Decimal notation)

4) SizeBits - as Ulong - Set/Get the current precision of DoubleNum, in bits.

5) Sign - As Int32 - Sign DoubleNum


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(FormatE = true (Optional), _base = 10 (Optional), n_digits = 0 (Optional), separator = "." (Optional)) - as String - Convert DoubleNum to a string.
FormatE: True - Scientific notation, False - Decimal notation.
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.
Separator - symbol used to separate the integer part from the fractional part of a number.

7) Get_String(Exponent, 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.
The generated string is a fraction, with an implicit radix point immediately to the left of the first digit. The applicable exponent is written through the expptr pointer. For example, the number 3.1416 would be returned as string "31416" and exponent 1.

8) Help() - As System.Windows.Forms - DoubleNum Class Reference

9) Multiply(DoubleNum, DoubleNum) - No - Returns the product of two DoubleNum values in this DoubleNum

10) Negate(DoubleNum) - No - Negates a set DoubleNum value and returns the result in this DoubleNum

11) Power(DoubleNum, Int32) - No - Raises a*DoubleNum*value to the power of a specified value (Int32) and returns the result in this DoubleNum

12) Root(DoubleNum) - No- Return root this DoubleNum

13) SetString(String, Base = 10 (Optional)) - 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.

14) Subtract(DoubleNum, DoubleNum) - No - Subtracts one DoubleNum value from another and returns the result in this DoubleNum

Пример использования на VBA после подключения/открытия надстройки .xll
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 = 512      'задаем размер в битах (длина мантиссы) 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"
'При DN.SizeBits = 512, результат "0.702728368574942333670982037936573775804285333327693943658137742171854086324251183843685273237111564843880316598297109847502508123103123822382864370276496515E+54"
LN.Help 'Справка
End Sub

27/03/2018
Продолжение в следующем моем блоге...
Вложения
Тип файла: rar LongNum_Excel_0.0.0.4.rar (1.03 Мб, 45 просмотров)
Тип файла: rar LongNum_Excel_0.0.0.5.rar (921.4 Кб, 65 просмотров)
Размещено в VBA, C#.NET
Просмотров 1090 Комментарии 2
Всего комментариев 2
Комментарии
  1. Старый комментарий
    Запись от bedvit размещена 11.08.2016 в 11:39 bedvit вне форума
  2. Старый комментарий
    Аватар для bedvit
    Версия 0.0.0.5:
    1. Создан механизм проверки правильного парсинга String (Scientific notation, Decimal notation) для DoubleNum
    2. Оптимизированы некоторые функции
    3. Добавлен вывод DoubleNum как в дробном виде (с точкой), так и в экспоненциальной записи.
    4. Добавлено несколько новых функций
    5. Оптимизирован размер для библиотеки х64.

    Пока не сделано:
    1.Переполнение по exponent библиотекой сейчас НЕ ПРОВЕРЯЕТСЯ
    2.RationalNum Class
    Запись от bedvit размещена 13.09.2016 в 12:49 bedvit вне форума
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru