09.11.2019, 15:53
|
Новичок на форуме
|
|
Регистрация: 06.11.2019
Сообщений: 4
|
|
Возведение в степень
Здравствуйте!
Изучаю алгоритм RSA шифрования, и столкнулся с проблемой. Как в JS правильно возводить в трехзначную и более степень ? Например:
let p = (i**e) % n;
где е = 2003 и n= 4399
|
|
09.11.2019, 15:55
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,990
|
|
|
|
09.11.2019, 16:15
|
Новичок на форуме
|
|
Регистрация: 06.11.2019
Сообщений: 4
|
|
Math.pow() и ** при возведении в такую большую степень выбрасывают NaN, как решать подобную проблему помимо использования BigInt, который не дает делить по модулю из-за разницы типов ?
|
|
09.11.2019, 16:30
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,990
|
|
Сообщение от Hokage777
|
помимо использования BigInt, который не дает делить по модулю
|
Кто такое сказал?
|
|
09.11.2019, 16:48
|
|
Профессор
|
|
Регистрация: 25.10.2016
Сообщений: 1,012
|
|
Если нужен только остаток, то его можно брать в ходе работы, тогда мы не упарываемся в километровые числа. Самый простой вариант - при возведении в степень n**p сделать цикл из p умножений на n (после каждого берем остаток), но гораздо быстрее смотреть биты числа р и умножать на соответствующие им значения n**(2**i)
// вычисляет (n ** p) % m
function powMod(n, p, m) {
if (n < 1) { return 0; }
if (m < 0) { m = 0; }
p = Math.round(p);
n = n % m;
var r = 1;
while (p >= 1) {
if (p % 2) {
r = (r * n) % m;
}
n = (n * n) % m;
p = Math.floor(p / 2);
}
return r;
}
alert(powMod(34546, 68883, 2437));
в хроме на относительно больших числах это работает быстрее "прямого" вычисления с BigInt
Последний раз редактировалось Alexandroppolus, 09.11.2019 в 16:59.
|
|
09.11.2019, 18:28
|
|
Профессор
|
|
Регистрация: 20.12.2009
Сообщений: 1,714
|
|
Сообщение от Hokage777
|
как решать подобную проблему помимо использования BigInt, который не дает делить по модулю из-за разницы типов ?
|
Всё таки даёт...
function powToMod(base, power, module) {
if(power === 1n) return base;
if(power % 2n === 0n) return powToMod(base, power / 2n, module) ** 2n % module;
return powToMod(base, power - 1n, module) * base % module;
}
alert(powToMod(366142356n, 1447804911n, 219020071n));
Alexandroppolus, проверьте свой алгоритм, powToMod(366142356n, 1447804911n, 219020071n) должно выдавать 38504623
Проверял также тут — https://www.wolframalpha.com/input/?...11mod219020071
|
|
09.11.2019, 19:44
|
|
Профессор
|
|
Регистрация: 25.10.2016
Сообщений: 1,012
|
|
Сообщение от Malleys
|
Alexandroppolus, проверьте свой алгоритм, powToMod(366142356n, 1447804911n, 219020071n) должно выдавать 38504623
|
тот же вариант для БигИнта, работает правильно
function powModBig(n, p, m) {
if (n < 1n) { return 0n; }
if (m < 0n) { m = 0n; }
n = n % m;
var r = 1n;
while (p >= 1n) {
if (p % 2n) {
r = (r * n) % m;
}
n = (n * n) % m;
p = p / 2n;
}
return r;
}
alert(powModBig(366142356n, 1447804911n, 219020071n))
а по сути здесь абсолютно тот же алгоритм, как у тебя, только без рекурсии.
----
вариант для обычных чисел не может с такими параметрами, потому что 366142356 % 219020071 дает большое число, которое при возведении в квадрат вылезает за пределы нумбера.
Последний раз редактировалось Alexandroppolus, 09.11.2019 в 19:46.
|
|
18.04.2021, 08:48
|
Новичок на форуме
|
|
Регистрация: 18.04.2021
Сообщений: 1
|
|
Ребят, я тут понимаю все очень серьезно, теоремы гаусса, БинИнт и прочие ругательства, но почему встроенный калькулятор не может корректно возвести в куб одну десятую и две десятых?
function fn01 (n) {return n * n * n}
function fn02 (n) {return n ** 3}
console.log(fn01(0.1))
console.log(fn02(0.1))
console.log(Math.pow(0.1, 3))
console.log(fn01(0.2))
console.log(fn02(0.2))
console.log(Math.pow(0.2, 3))
|
|
19.04.2021, 10:19
|
|
Профессор
|
|
Регистрация: 25.10.2016
Сообщений: 1,012
|
|
|
|
|
|