Python和Node.js中相同的函数返回不同的结果

时间:2018-08-21 15:00:16

标签: javascript python node.js

我正在将一个项目从Python过渡到Node.js-到目前为止一切都很好。我有一个功能,应该将某人拥有的EXP数量转换为一个级别。我试图将工作功能从Python重写为Node.js,但是功能返回的答案完全不同,我不知道为什么。

Python:

def calculateLevel(exp):
    if exp < 83: return 1
    else:
        calcExp = 0
        for level in range(1, 1000):
            diff = int(level + 300 * math.pow(2, float(level)/7))
            calcExp += diff
            if exp < calcExp//4:
                break
        return level

Node.js:

const _ = require("underscore");
// ...
function calculateLevel(exp) {
    return new Promise((resolve, reject) => {
        if (exp < 83) resolve(1);
        else {
            var calcExp = 0;
            for (var i in _.range(1, 1000)) {
                calcExp += parseInt(i + 300 * Math.pow(2, i/7));
                if (exp < Math.floor(calcExp/4)) {
                    resolve(i);
                    break;
                }
            }
        }
    });
}

例如,Python中的calculateLevel(123456)返回51(正确答案),而Node.js中的await calculateLevel(123456);返回15(错误答案)。

很明显,Node.js版本出了点问题,但我不知道这是什么。

任何帮助将不胜感激。预先感谢。

4 个答案:

答案 0 :(得分:2)

在Python中:

for i in range(1, 10)
   print(i)

将创建序列到1 2 3 4 5 6 7 8 9

JavaScript中的for...in将遍历键而不是值。

因此for (var i in _.range(1, 1000)) {将始终为0 ... 999

将其更改为for...of

function calculateLevel(exp) {
    return new Promise((resolve, reject) => {
        if (exp < 83) resolve(1);
        else {
            var calcExp = 0;
            for (var i of _.range(1, 999)) {
                calcExp += parseInt(i + 300 * Math.pow(2, i/7));
                if (exp < Math.floor(calcExp/4)) {
                    resolve(i);
                    break;
                }
            }
        }
    });
}

此外,不清楚为什么在此处使用Promise,因为此处没有任何异步代码。因此,您可以在此处完全删除Promise。

const _ = require("underscore");
// ...
function calculateLevel(exp) {
  if (exp < 83) return 1;
  else {
      var calcExp = 0;
      for (var i of _.range(1, 1000)) {
          calcExp += parseInt(i + 300 * Math.pow(2, i/7));
          if (exp < Math.floor(calcExp/4)) {
              break;
          }
      }
      return i;
  }
}

console.log(calculateLevel(123456))

答案 1 :(得分:0)

if (exp < Math.floor(calcExp/4)) {
                    resolve(i);
                    break;
                }

应该是

if (exp < Math.floor(calcExp/4)) {
                        break;
                    }
resolve(i)

答案 2 :(得分:0)

我运行了这段代码:

function calculateLevel(exp) {
    return new Promise((resolve, reject) => {
        if (exp < 83) resolve(1);
        else {
            var calcExp = 0;
            for (var i=1; i<1000; i++) {
                calcExp += parseInt(i + 300 * Math.pow(2, i/7));
                if (exp < Math.floor(calcExp/4)) {
                    resolve(i);
                    break;
                }
            }
        }
    }); }

console.log(calculateLevel(123456));

返回51。

可能是其他原因造成的。

答案 3 :(得分:0)

添加我的意见,因为您已经有了一个可以接受的答案。

尽管您将Python代码块转换为Javascript,但我觉得您实际上不必使用相同的语法和方法名称。

例如,如果我们在Python和JS中采用以下代码块;

Python:

def calculateLevel(exp):
    if exp < 83: return 1
    else:
        calcExp = 0
        for level in range(1, 1000):
            diff = int(level + 300 * math.pow(2, float(level)/7))
            calcExp += diff
            if exp < calcExp//4:
                break
        return level

注意:这里使用for level in range(1, 1000):

同样可以通过使用while循环来完成。所以看起来可能像这样:

level = 0
while level <= 1000:
    diff = int(level + 300 * math.pow(2, float(level)/7))
    calcExp += diff
    if exp < calcExp//4:
        break
return level

但是在Python中循环for in range()比使用while循环更有效。如果运行简单的基准测试,则可以看到以下结果。

  

for in range():在0.000秒内调用55个函数

     

while:在0.001秒内调用1650个函数

尽管Python就是这种情况,但Javascript(和使用下划线的range()函数的方法)却大不相同。尽管函数名看起来很相似,但这并不意味着它们的性能与Python。

实际上,循环_.range()比循环while慢得多。如果您查看一些基准测试结果,将会看到类似以下的内容:

Using _.range(1, 1000):慢67.67%

https://jsbench.me/b2jl4vvgnw/1

因此,我认为最好使用while循环编写此代码,并稍作修改,将其编写为:

function calculateLevel(exp) {
    var level = 1;

    if (exp > 83){
        var calcExp = 0;
        while(level <= 1000){
            calcExp += parseInt(level + 300 * Math.pow(2, level/7));
            if (exp < Math.floor(calcExp/4))
                break;
            level++;
        }
    }
    return level;
}

希望有帮助!