Одинаковый код на Python и JavaScript работает по-разному

268
11 ноября 2017, 14:40

Почему одинаковый код на разных языках работает по-разному? На Python работает корректно, на JS - нет. Я написал "аттакер" на линейно-конгруэнтный генератор, в котором используется модульная инверсия. Пример кода на Python, который работает корректно:

def crackUnknownIncrement(states, modulus, multiplier):
   increment = (states[1] - states[0] * multiplier) % modulus
   return modulus, multiplier, increment

def crackUnknownMultiplier(states, modulus):
    multiplier = (states[2] - states[1]) * modinv(states[1] - states[0], modulus) % modulus
    return crackUnknownIncrement(states, modulus, multiplier)

def egcd(a, b):
    if a == 0:
        return b, 0, 1
    else:
        g, x, y = egcd(b % a, a)
        return g, y - (b // a) * x, x

def modinv(b, n):
    g, x, _ = egcd(b, n)
    if g == 1:
        return x % n
def prediction(multiplier, increment, modulus, state):
    print((multiplier * state + increment) % modulus)

print(crackUnknownMultiplier([-750039887, 1964596828, -2125634037], 4294967296))
prediction(1664525, 1013904223, 4294967296, -2125634037)

А вот кусок кода на JS, который абсолютно такой же, но работает, почему-то неправильно:

function getIncrement(values, modulus, multiplier) {
  let increment = (values[1] - values[0] * multiplier) % modulus;
  return [ modulus, multiplier, increment ];
}
function getMultiplier(values, modulus) {
  let multiplier = (values[2] - values[1]) * modinv(values[1] - values[0], modulus) % modulus;
  return getIncrement(values, modulus, multiplier)
}
function egcd(a, b) {
  if (a == 0) {
    return [b, 0, 1];
  }
  else {
    let [g, x, y] = egcd(b % a, a);
    return [g, y - Math.floor(b / a) * x, x];
  }
}
function modinv(b, n) {
  let [g, x, y] = egcd(b, n);
  if (g == 1)
    return x % n;
}

Есть подозрение, что работает неверно модульная инверсия, но почему?

Answer 1

У вас в функции getMultiplier в этом участке кода (values[2] - values[1]) * modinv(values[1] - values[0], modulus) получается число меньше чем может переварить JavaScript, вот такое -8075061793818843000, а в python в этом же месте получается число -8075061793818843635. Вот из-за этого и возникает ошибка, так как в JavaScript числа меньшие чем -9007199254740992 представляются не точно.

Для решения этой проблемы можно воспользоваться модулем big-integer.

А воспроизвести ошибку можно так:

// XXX BROKEN 
var x = -90071992547409921231; 
document.write(x);

READ ALSO
Реализация Service Worker на Angular 2/4

Реализация Service Worker на Angular 2/4

Вопрос такой - как правильно реализовать Service Worker на Angular 2/4? Меня именно интересуют уведомления, когда приложение не активно (вкладка не открыта),...

214
Почему typeof пропускает функцию в цикле for in?

Почему typeof пропускает функцию в цикле for in?

Есть метод который перебирает объект и записывает только свои свойства, без методовНо проверка typeof на функцию не работает, и метод тоже записывается

218
Не работают события keyup/keypress/keydown

Не работают события keyup/keypress/keydown

Необходимо сделать следующий функционал, чтобы при вводе символов с клавиатуры в input вызывалось модальное окно и то что юзер ввел в первом...

322
Не работают breakpoint в slick slider

Не работают breakpoint в slick slider

Добрый день друзья, у меня проблема с адаптацией моего слайдера

821