【问题标题】:Different results for the same problem solution in node.js and pythonnode.js和python中相同问题解决方案的不同结果
【发布时间】:2020-02-05 13:09:30
【问题描述】:

我用一些代码解决了以下 leetCode 问题:


你有d 骰子,每个骰子都有f 面,编号为 1、2、...、f。

返回以 10^9 + 7 为模的可能方式的数量来掷骰子,因此正面朝上的数字之和等于 t


我制作了两个版本的解决方案代码,一个在 node.js 中使用mathjs,另一个在 python 中使用数学模块。

在 node.js 中

const { combinations: comb, bignumber: Big } = require("mathjs");

function dice(d, f, t) {
    if (t > d * f || t < d) return 0;

    var result = Big(0);
    var i = 0;
    var sign = 1;
    var n = t - 1;
    var k = t - d;

    while (k >= 0 && i <= d) {
        result = result.add(
            comb(Big(d), Big(i))
                .times(comb(Big(n), Big(k)))
                .times(sign)
        );

        i++;
        n -= f;
        k -= f;
        sign *= -1;
    }

    return result;
}

console.log(
    dice(30, 30, 500).mod(
        Big(10)
            .pow(9)
            .add(7)
    )
);

在python中:

import math


def dice(d, f, t):
    if t > d * f or t < d:
        return 0

    result = 0
    i = 0
    sign = 1
    n = t - 1
    k = t - d

    while k >= 0 and i <= d:
        result += math.comb(d, i) * math.comb(n, k) * sign
        i += 1
        n -= f
        k -= f
        sign *= -1

    return result


print(dice(30, 30, 500) % (math.pow(10, 9) + 7))


现在,当我使用以下参数运行代码时:d=30 f=30 t=500(每个版本代码的最后一行),我希望结果是 222616187

在 node.js 版本中,这正是我得到的。

但在 python 版本中,我得到811448245.0 我不知道为什么会这样。

那么为什么结果会有差异呢?

【问题讨论】:

  • 注意dice(30, 30, 500)的结果不能用64位浮点数准确表示。 -14999044413600247749080617 关闭。

标签: javascript python combinatorics bignum arbitrary-precision


【解决方案1】:

math 模块使用float,而不是任意精度int

math - Mathematical functions

[...]

本模块提供以下功能。除非当 另有明确说明,所有返回值都是浮点数。

由于math.pow 返回float% 的前导参数也被转换为floatdice(30, 30, 500) 的结果太大,无法准确表示为 float。它的float 表示被-14999044413600247749080617 关闭。

** 运算符及其函数版本operator.pow 不强制进行float 转换,如果所有参数都是整数,则提供整数。

>>> print(dice(30, 30, 500) % (10 ** 9 + 7))
222616187

【讨论】:

  • 内置的pow 也有理想的行为。
【解决方案2】:

以一种奇怪的方式解决了。事实证明,math.pow 返回一个 float 而不是 int 并且以某种方式被窃听。我认为 int % float 在其中具有不同的强制转换操作,并且编译器对其进行了不同的处理。可以进一步调查。如果您将其转换为 int,那将是您的答案。

import math


def dice(d, f, t):
    if t > d * f or t < d:
        return 0

    result = 0
    i = 0
    sign = 1
    n = t - 1
    k = t - d

    while k >= 0 and i <= d:
        result += math.comb(d, i) * math.comb(n, k) * sign
        i += 1
        n -= f
        k -= f
        sign *= -1

    return result


print(dice(30, 30, 500) % int((math.pow(10, 9) + 7)))

【讨论】:

  • 看到你的回答后,我很好奇,我尝试用10**9 +7 替换math.pow(10 , 9)+7,但没有转换为int,我得到了正确的结果,**math.pow 有何不同?
  • Math.pow(在 c 中)function 接受参数并将它们转换为双精度(c 中的双精度,python 中的浮点数)。默认 pow 不这样做。这种强制转换操作使背景中的一切都变得不同,甚至在编译器中也是如此。 Differences 默认和 math.pow 在这里。你也可以看看这个。
猜你喜欢
  • 2014-11-21
  • 2012-02-07
  • 1970-01-01
  • 2011-08-31
  • 2016-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多