2

I tried performing Modular Exponentiation in Javascript to verify an algorithm and was shocked to find that Javascript was not giving accurate results compared to Python, Why is it so. I think it has something to do with the way Javascript handles datatypes(as Text), But I would like to know more about it and I know the purpose why both the langs were designed.

Modular Exponentiation result comparison in .js and .py

D4tech
  • 83
  • 1
  • 4
  • http://programmers.stackexchange.com/ might be a better place for this kind of question. – timonsku Nov 02 '13 at 14:04
  • This is a valid question –  Nov 02 '13 at 14:06
  • possible duplicate of [Is JavaScript's Floating-Point Math Broken?](http://stackoverflow.com/questions/588004/is-javascripts-floating-point-math-broken) – plalx Nov 02 '13 at 14:10
  • @PaulGreen What makes you think that? –  Nov 02 '13 at 14:13
  • @delnan sounded more like a general question about the inner working of both languages. Which is what I thought is more of a thing for programmers.stackexchange.com was just a suggestion though – timonsku Nov 02 '13 at 14:28

2 Answers2

10

It gets a bit clearer, when you look at the intermediary results before the modulo operation first:

> Math.pow(17, 22)
1.1745628765211486e+27
>>> pow(17, 22)
1174562876521148458974062689

As you can see, the Python result has a lot more digits than the JavaScript result. This is due to how each language handles numbers or integers.

Python has an int type, which is basically unlimited: “These represent numbers in an unlimited range, subject to available (virtual) memory only.” So as long as you have memory available, the integers that can be represented with this type can be as big as you want—without any loss in precision.

Enter JavaScript and the ECMA standard. Unlike Python and other languages, we only have a single type responsible for all numeric types: Number. This type holds integers and decimals without any differentiation. They are internally represented as double precision floating point numbers. As such, they are subject to those restrictions, allowing only a certain amount of precision for big numbers. Hence, the best you can get for 17^22 is the above result, with the rest of the precision lost in the process.


If you are not too focused on performance, you could write your own pow function that additional takes a third parameter to apply a modulo operation to the result, similar to how Python’s pow does.

function modpow (base, exponent, modulo) {
    var result = base;
    while (exponent > 1 ) {
        result = (result * base) % modulo;
        exponent--;
    }
    return result;
}

Of course, this is a lot less efficient than the internal pow and only works for integer exponents, but at least it would solve your job correctly:

> modpow(17, 22, 21)
4
poke
  • 369,085
  • 72
  • 557
  • 602
8

The pow() function in Python returns an integer result for integer inputs:

>>> pow(17, 22)
1174562876521148458974062689L

This is not the same function as what Math.pow() gives you, which uses floating point results:

> Math.pow(17, 22)
  1.1745628765211486e+27

The equivalent function in Python is math.pow():

>>> import math
>>> math.pow(17, 22)
1.1745628765211484e+27

and suffers from the same limitations, albeit subtly different in actual result:

>>> math.pow(17, 22) % 21
3.0

JavaScript only has the Number type, which limits JS arithmetic to float precision, always, while Python's support for a memory-bound integer type gives it more scope for precision.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343