Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нем неправильно. Необходимо обновить браузер или попробовать использовать другой.
Кто-нибудь занимался библиотекой GMP.au3? - Быстрая обработка больших чисел.
Там опубликовано пару десятков основных функций, но потенциал dll гораздо больше, есть ли у кого ещё какие-нибудь...
Описание в инете на англ. в С+ есть, но не по моим масштабам...
Преимущество библиотеки очевидна:
1. Она быстрее BigNum.au3
2. Есть разделение - работа с целыми и не целыми числами
3. Можно настроить отдельными функциями для работы с большими экспоненциальными и шестнадцатеричными числами типа '3.22710329289562e+19' и '0x...'
4. Более высокая точность вычисления корней/деления и мн.др.
========================
Спустя некоторое время была создана UDF - GMP_PLUS.au3
Версия 1.0 - 12.03.2023 - 22 функции для целых чисел
Версия 1.1 - 13.03.2023 - +11 функции для целых чисел
Версия 1.2 - 14.03.2023 - +17 функции для разных чисел
Версия 1.3 - 15.03.2023 - + 8 функции для разных чисел + Необходимые изменения в GMP.au3 (версия 2.0)
Версия 1.4 - 22.03.2023 - + 55 функции для разных чисел + Необходимые изменения в GMP.au3 (версия 2.1)
Архив с постоянной ссылкой, в нём:
Тут супер личного опыта и не надо, хотя провел сотни тестов - простой тест на сложение больших чисел даёт разницу в 4 раза (это только на 10.000 - далее медлительность BigNum.au3 растёт) , не говоря уж о делении и т.д., о получении НОД, НОК больших чисел и других преобразованиях....
Код:
#include <BigNum.au3>
#include <GMP.au3>
$hTimer=TimerInit()
$n1=_F_Bignum(10000)
$iDiff1=TimerDiff($hTimer)/1000
$hTimer=TimerInit()
$n2=_F_GMP(10000)
$iDiff2=TimerDiff($hTimer)/1000
MsgBox(4096,'Результат','$iDiff1 =>'&$iDiff1&'<='&@CRLF&'$iDiff2 =>'&$iDiff2&'<=')
MsgBox(4096,'Результат','$n1 =>'&$n1&'<='&@CRLF&'$n2 =>'&$n2&'<=')
Func _F_Bignum($iIndex)
Local $n=0,$k=1,$tmp
For $i=1 To $iIndex-1
Dim $tmp=_BigNum_Add($n,$k),$n=$k,$k=$tmp
Next
Return $n
EndFunc
Func _F_GMP($iIndex)
Local $n=0,$k=1,$tmp
For $i=1 To $iIndex-1
Dim $tmp=_GMP_AddInteger($n,$k),$n=$k,$k=$tmp
Next
Return $n
EndFunc
В поиске скорости нашёл Mat.au3, она работает по другому принципу - тоже быстрее BigNum.au3 на сложение/вычитание, но медленнее GMP.au3
Если есть знатоки DLL и C+ увлекающиеся скоростью, то вы можете помочь - в создании новых функций...
Сообщение автоматически объединено:
Вот ещё один пример скорости, недавно занимался простыми числами, на офф. форуме встретил 10-ки тем и более 30 функций от простых до самых экзотических.
А цель простая проверить является ли число простым, ни одна не справилась с большими числами или очень и очень долго, если цифр менее 15...
Обратился к функционалу GMP и методом тыка нашёл __gmpz_nextprime - ищет следующее простое число, относительно заданного целого, скорость тоже порадовала - миллисекунды
Чтобы проверить на валидность, необходимо отнять 1 от числа и найти следующее простое, если они совпали, то число является простым...
Этой функцией _GMP_Next_Prime так же разрешается вопрос о получении простых чисел в диапазоне, т.к. все Autoit методы, которые я встречал, начинаются с 2,3,5, заполняя массив или перебором... но это отдельный разговор.
Код:
#include <String.au3>
#include <BigNum.au3>
#include <GMP.au3>
; проверки этого числа _IsBigNumComposite я не дождался...
; $iIndex='7329484627889245056234114089163872541489731234351678654257'
$iIndex='737373737373761'
$hTimer=TimerInit()
$n=_IsBigNumComposite($iIndex)
MsgBox(4096,'Время',TimerDiff($hTimer)/1000)
MsgBox(4096,'$n',$n)
$hTimer=TimerInit()
$n=__IsPrime_GMP($iIndex)
MsgBox(4096,'Время',TimerDiff($hTimer)/1000)
MsgBox(4096,'$n',$n)
$iIndex='7329484627889245056234114089163872541489731234351678654257'
$hTimer=TimerInit()
$n=__IsPrime_GMP($iIndex)
MsgBox(4096,'Время',TimerDiff($hTimer)/1000)
MsgBox(4096,'$n',$n)
; является ли число простым числом, возвращает -1, если не целое; 0 - составное; 1- простое
Func __IsPrime_GMP($n)
Return StringInStr($n,'.')?-1:(StringCompare($n,_GMP_Next_Prime(_GMP_SubInteger($n,1)))?0:1)
EndFunc
; ищет следующее простое число, относительно заданного целого
Func _GMP_Next_Prime($sValue)
Local $t_Value=DllStructCreate($tag_mpz_t),$p_Value=DllStructGetPtr($t_Value)
_GMPz_Init_Set_Str($p_Value,$sValue)
_GMPz_NextPrime($p_Value,$p_Value)
$sRes=_GMPz_get_Str($p_Value)
_GMPz_Clear($p_Value)
Return $sRes
EndFunc
Func _GMPz_NextPrime($pResult,$pVal)
DllCall($hDLL_GMP,'none:cdecl','__gmpz_nextprime','ptr',$pResult,'ptr',$pVal)
EndFunc
Func _IsBigNumComposite($n)
If Mod(StringRight($n, 1), 2) = 0 Then Return
Local $n_1 = _BigNum_Sub($n, "1"), $t, $q = $n_1, $a, $e, $b, $any
While Mod(StringRight($q, 1), 2) = 0
$t += 1
$q = _BigNum_Div($q, 2)
WEnd
For $c = 1 To 10
$a = String(Random(2, 100, 1))
$b = __BigNum_PowerMod($a, $q, $n)
If $b <> "1" Then
For $e = 1 To $t
If $b = $n_1 Then ContinueLoop
$b = _BigNum_Mod(_BigNum_Mul($b, $b), $n)
Next
If $b <> $n_1 Then Return
EndIf
Next
Return 1
EndFunc
Func __BigNum_PowerMod($n, $e, $k)
If Not __BigNum_IsValid0($n) Then Return SetError(1, 0, -1)
If Not __BigNum_IsValid0($e) Then Return SetError(2, 0, -1)
If Not __BigNum_IsValid0($k) Then Return SetError(3, 0, -1)
Local $res = "1"
While $e <> "0"
If Mod(StringRight($e, 1), 2) Then
$res = _BigNum_Mod(_BigNum_Mul($res, $n), $k)
$e = _BigNum_Sub($e, "1")
EndIf
$n = _BigNum_Mod(_BigNum_Mul($n, $n), $k)
$e = _BigNum_Div($e, "2")
WEnd
Return $res
EndFunc ;==>__BigNum_PowerMod
Func __BigNum_IsValid0($sX)
If StringRegExp($sX, "[^0-9.-]") Then Return False
Return True
EndFunc
Продолжу дальше изучать, здесь тоже встретил информацию, но описания маловато...
---
Позже увидел mpz_probab_prime_p, которая должна проверять валидность простого числа, но подключить в Autoit пока не получилось
При изучении PureBasic встретил две интересные вещи: Lizard — язык сценариев для символьных вычислений, произвольных больших и точных чисел, параллельных вычислений и многого другого. По сути это внешняя библиотека с анализатором выражений и ей всего лишь надо писать оболочку для запросов к dll. BigInt - это модуль написанный на PureBasic и при желании его можно оформить как dll и скомпилировать. В отличии от BigNum.au3 работает быстрее за счёт машинного кода. Я уже пробовал на нём писать программу "генератор пароля" и если для BigNum.au3 я отказался от вычислений в режиме реального времени при вводе ключевого слова и сделал кнопку, то в PureBasic работает в режиме реального времени без торможений.
Когда они будут оформлены для теста на Autoit, тогда будет о чём поговорить - проверить скорость, а пока...
---
Что касается скорости GMP, выяснил, что внутри самой библиотеки, можно ещё повысить скорость в несколько раз, при работе с многоразовыми вычислениями. Дело в том что каждая функция создаёт структуру для 2-х чисел, а в конце закрывает _GMPz_Clear. Если структуру 1-го не закрывать, а во вторую передавать следующее число, то скорость обработки увеличивается. На примере у меня показывает 30% при сумме 3-х чисел в цикле 10000. А значит функции _GMP_ParseFloat и _GMP_ParseInt можно ускорить, соответственно полностью их переписав, тем более там кучи всего полезного нет - факториала...
Код:
#include <GMP.au3>
$sValue1='111111111111111111111111111'
$sValue2='222222222222222222222222222'
$sValue3='444444444444444444444444444'
$n=10000
$hTimer=TimerInit()
For $i=1 To $n
$n1=_GMP_AddInteger3($sValue1,$sValue2,$sValue3)
Next
$iDiff1=TimerDiff($hTimer)/1000
$hTimer=TimerInit()
For $i=1 To $n
$n2=_GMP_AddInteger(_GMP_AddInteger($sValue1,$sValue2),$sValue3)
Next
$iDiff2=TimerDiff($hTimer)/1000
MsgBox(4096,'Результат','$iDiff1 =>'&$iDiff1&'<='&@CRLF&'$iDiff2 =>'&$iDiff2&'<=')
MsgBox(4096,'Результат','$n1 =>'&$n1&'<='&@CRLF&'$n2 =>'&$n2&'<=')
; Суммирует 3 числа
Func _GMP_AddInteger3($sValue1,$sValue2,$sValue3)
Local $t_Value1=DllStructCreate($tag_mpz_t),$t_Value2=DllStructCreate($tag_mpz_t)
Local $p_Value1=DllStructGetPtr($t_Value1),$p_Value2=DllStructGetPtr($t_Value2)
_GMPz_Init_Set_Str($p_Value1,$sValue1)
_GMPz_Init_Set_Str($p_Value2,$sValue2)
_GMPz_Add($p_Value1,$p_Value1,$p_Value2)
_GMPz_Init_Set_Str($p_Value2,$sValue3)
_GMPz_Add($p_Value1,$p_Value1,$p_Value2)
Local $sRes=_GMPz_get_Str($p_Value1)
_GMPz_Clear($p_Value1)
_GMPz_Clear($p_Value2)
Return $sRes
EndFunc
Нашёл десятка три функций, вернее по аналогии примеров GMP.au3 получилось их составить. Пока не публикую, я никогда не создавал UDF - видимо повозится надо с описаниями, но уже хорошо почти всё нужное нашлось.
Пока не получается составить функции сравнения двух чисел, они идут с "cmp" __gmpz_cmp, возможно у кого-то это получится.
В архиве gmp.h.htm, GMP.au3, gmp.dll (вроде последняя версия) GMP.zip
Сообщение автоматически объединено:
Пока я тут разбираюсь и структурирую, появился вопрос к знатокам DLL, возьмём любую функцию, к примеру эту:
Код:
Func _GMP_HexToInt($sValue)
Local $t_Value = DllStructCreate($tag_mpz_t)
Local $p_Value = DllStructGetPtr($t_Value)
_GMPz_Init_Set_Str($p_Value, $sValue, 16)
Local $sRes = _GMPz_get_Str($p_Value)
_GMPz_Clear($p_Value)
$t_Value = 0
Return $sRes
EndFunc
В конце каждой команды стоит _GMPz_Clear($p_Value), а то и несколько...
А есть ли в этом смысл? Если данные переменных, объявленные в Local обнуляются атоматически при выходе из функции...
Или структура остаётся в памяти?
Запись $t_Value = 0 из этой же серии - нужна ли? Мы же $sRes ничего не делаем, $sRes передаётся через Return и данные локальной переменной очищаются внутренним функционалом Autoit
---
Дошло _GMPz_Clear нужен, как и функции различные _WinAPI ...Destroy... для закрытия/удаления/очищения дескрипторов...
Версию GMP.au3 из архива вы можете заменить, т.к. у меня было их 2 штуки с англ.сайта - но в одном недоставало того что было в другом - объединил общее...
Ссылку добавил в первое сообщение - думаю там ещё более 50 функций точно будет
Скачать GMP
Что касается скорости, то это видно на вроде бы незначительных функциях _GMP_AddInteger и _GMP_Add_Integer_ui
Код:
#include <GMP_PLUS.au3>
; ждать примерно 10 секунд...
$sValue1='111111111111111111111'
$n=100000
$hTimer=TimerInit()
For $i=1 To $n
$sValue1=_GMP_AddInteger($sValue1,$i)
Next
$iDiff1=TimerDiff($hTimer)/1000
$n1=$sValue1
$sValue1='111111111111111111111'
$hTimer=TimerInit()
For $i=1 To $n
$sValue1=_GMP_Add_Integer_ui($sValue1,$i)
Next
$iDiff2=TimerDiff($hTimer)/1000
$n2=$sValue1
MsgBox(4096,'Результат','$iDiff1 =>'&$iDiff1&'<='&@CRLF&'$iDiff2 =>'&$iDiff2&'<=')
MsgBox(4096,'Результат','$n1 =>'&$n1&'<='&@CRLF&'$n2 =>'&$n2&'<=')
Разница 30% - потому что _GMP_AddInteger() создаёт ДВЕ структуры для 2-х чисел, а _GMP_Add_Integer_ui() - одну
И это тоже можно ускорить - пример выше со сложением 3-х цифр.
Но тут нужно прочитать описание - это актульно, если первое число БОЛЬШОЕ, а второе маленькое... Если оба больших, то конечно же _GMP_AddInteger
Сообщение автоматически объединено:
Добавил ещё 11 функций, дело постепенно продвигается ))
Произведены необходимые изменения в GMP.au3 - Версия: 2.0
Код:
- Добавлены общие функции для очистки нескольких данных
; _GMPz_Clears
; _GMPf_Clears
- Добавлены функции для общей автоматизации
; _GMPz_ui_Sub
; _GMPz_ui_Pow_ui
; _GMPf_ui_Div
; _GMPf_ui_Sub
- Изменены ряд функций
- Изменена структура UDF - к с основным функциям перенесены соответствующие DLL функции
- К некоторым функциям добавлены комментарии/описание
- Добавлена глобальная переменная $GMP_BASE_INT
- Добавлены функции
; _GMP_Set_Base_Int
Т.е добавлены функции, которых не хватало и добавлены новые, кроме того
Добавлена глобальная переменная $GMP_BASE_INT и функция _GMP_Set_Base_Int
Это позволяет для целых чисел "на лету" менять систему счисления и вычислять не только десятичные, но и другие (от 2 до 62)
Пример:
Одна из них _GMP_BaseToBase, которая конвертирует из одной системы счисления в другую
На форумах видел сотни конвертных функций, все они либо имеют ограничения, либо медленные, т.к. идёт перебор символов... эта опять же порадовала скоростью при длинных данных
Пример:
Код:
#include <GMP_PLUS.au3>
$sValue='81111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111118'
; перевод в двоичную и обратно
$sRes=_GMP_BaseToBase($sValue,10,2)
MsgBox(4096,'$sRes',$sRes)
$sRes=_GMP_BaseToBase($sRes,2,10)
MsgBox(4096,'$sRes',$sRes)
; перевод в шестнадцатеричную и обратно
$sRes=_GMP_BaseToBase($sValue,10,16)
MsgBox(4096,'$sRes',$sRes)
$sRes=_GMP_BaseToBase($sRes,16,10)
MsgBox(4096,'$sRes',$sRes)
; перевод в тридцатишестиричную и обратно
$sRes=_GMP_BaseToBase($sValue,10,36)
MsgBox(4096,'$sRes',$sRes)
$sRes=_GMP_BaseToBase($sRes,36,10)
MsgBox(4096,'$sRes',$sRes)
; перевод в 50-ричную и обратно
$sRes=_GMP_BaseToBase($sValue,10,50)
MsgBox(4096,'$sRes',$sRes)
$sRes=_GMP_BaseToBase($sRes,50,10)
MsgBox(4096,'$sRes',$sRes)
Сообщение автоматически объединено:
Наверное последнее добавление - для себя всё что мне надо нашёл, + 55 функций
Обновлена GMP.au3, версия 2.1
Там конечно для скорости ещё многое чего надо (для себя уже переписываю/создаю) - отдельные функции внутри функций или дополнительные совместные, чтобы структуру не множить..., но это уж каждый для себя решит как этим воспользоваться - примеры есть.
Совет - функции с "длинными" имена лишь частный случай, для скорости нескольких преобразований числа лучше писать отдельную функцию передавая структуру числа из "короткой" функции в "короткую"... и только в конце очищать данные (я не просто так рядом с "описанной функцией" разместил соответстующую DLL функцию - она главная для будущих циклических изменений числа).
Об этом написано в англ. мануле: "Избегайте чрезмерной инициализации и очистки переменных, так как это может занять довольно много времени"
Для любителей есть ещё и libmpfr.dll - с логарифмами, косинусами... но это уже другая тема.
Вижу тема не сильно интересна, но возможно кому-то когда-то понадобится. Всем удачи в преобразовании больших числел, если что сообщайте об ошибках.
На англ. и немец. форуме темы тоже есть, но 10-летней давности без интереса, на PureBasic не увидел ни одной прямой ссылки (или "битые")... Хотелось бы посмотреть функции, т.к. язык схожий... , а то не зная синтаксиса C+ приходилось голову ломать что за переменную передать, то ли ptr, то ли ulong/int, то ли ещё что-то?... если есть такое на PureBasic, то хотелось бы видеть прямую ссылку на весь пакет, чтобы не терять времени, возможно бы что-то подкорректировалось и создалось новое
я там последним постом просил выложить библиотеки для всех ОС, так как все ссылки битые. Так что у меня ничего нет. Максимум я нашёл ещё эту ссылку, где я скачал libgmp-10.dll для x32 и с ней проверил код во втором посте темы на форуме PureBasic. И кстати буквально на днях ещё тут человек спрашивал либы для работы с большими числами. В итоге у тебя dll - 200кб, а там 600 кб. Поэтому я и просил, чтобы тот знающий чел выложил x64 и x32, если ему удалось скомпилировать для Windows, Linux и Mac OS. Но возможно ему удалось скачать с официального сайта, так как там где то была ссылка якобы скомпилированных либ, но я там не смог скачать, качаются только ссылки на исходники.
MPFR library built for Windows using msys2/mingw64 - emphasis87/libmpfr-msys2-mingw64
github.com
Там есть в архиве обе библиотеки в архиве...
x32_mpfr-3.1.5_gmp-6.1.2_standalone.7z
---
Я нашёл ищё и "сжатую" - но все они с разным размером работают... некоторые функции на самых первых типа gmp 1.5. возможно нет, т.к. давно изменялись
---
Если найдутся сами функции на PureBasic - будет хорошо на них глянуть
указатель пишется так *var (со звёздочкой) или взятие указателя @VAR, то есть получить указатель переменной var. Если функция запишет число в указатель, то оно мне просто доступно, я просто использую var как число, в которое было записано число функцией. В PureBasic нет беззнаковых чисел, то есть любой тип числа это диапазон от -127 до 127, то есть нет диапазона 0-127.
Если смотреть код, там *op.mpz, то это структура, после точки если одна буква - одна из abcdfilqsuw то это тип числа, строки и т.д. а если некое слово, то это объявление структуры, то есть в функцию передаётся указатель на структуру "mpz", выше смотри "Structure mpz" и ниже поля структуры с типами integer, то есть ".i" это и есть тип integer.
integer
4 байта (в 32-разрядном компиляторе) от - 2147483648 до +2147483647
8 байтов (в 64-разрядном компиляторе) от - 9223372036854775808 до +9223372036854775807
скачай справку по PureBasic, введи "типы" и увидешь страницу со всеми типами. Ну или вот онлайн страница по типам.
Честно ничего не понял (причём тут PureBasic, меня он не интересует и его справка тоже - если был код из него для GMP, то можно было бы сравнить) - я брал код с описания С+ или Delfi (возможно) и.др. - там никаких звёздочек, а точное определение [ptr|int|ulong|double|иногда срабатывали и другие типа uint64] - при тестировании при неточном определении происходило зависание скрипта, т.к. в GMP есть либо описанный, либо свой тип больших данных, (возможно до него не достучаться) - приведи пример любой функции в GMP_PLUS.au3 где нужно подправить (а могут быть и ошибки) - я исправлю...
В некоторых местах тянулась рука увеличить - но то, что значит "ulong" в Autoit не значит то же в gmp.dll - но при этом всём библиотека быстрая и дружелюбная))
Ты для чего тогда спрашиваешь как выглядят пурибэйсиковые указатели и тип данных и код, если тебе это ничего не нужно? А в том посте разве нет кода? Пиши точнее тогда, мне тоже собирать ссылки нет желания ради того чтобы услышать что тебе нафиг не надо, не надо так и пиши сразу, чтобы я не тратил время. Хотя из твоего вопроса я понял что ты хочешь по коду пурика узнать тип данных.
Такой код мне не нужен, не трать время... это всё есть и в англ. описании - там сложность в другом... значит не поняли друг друга. В общем на этом и закончим.