numpy 或 python 中的等效 matlab 函数 mod



我正在将一些代码从Matlab转换为Python。

在 matlab 中有一个函数mod它给出了模运算。

例如,以下示例显示了 matlabmod和等效的 numpyremainder操作之间的不同结果:

矩阵:

>> mod(6, 0.05)
ans =
0

嘟嘟:

np.remainder(6, 0.05) 
0.04999999999999967
np.mod(6, 0.05)
0.04999999999999967

Python 模数运算符给出的结果与 numpy 相同。

6%0.05
0.04999999999999967

python 中是否有任何内容可以提供与 Matlab 中相同的 mod 操作? 最好可以在numpy2D/3D 阵列上运行。

numpy文档说numpy.mod等同于matlabmod

这是问题的核心,在python中:

>>> 6/0.05 == 120
True
>>> 6//0.05 == 120  # this is 119 instead
False

6/0.05的浮点结果足够接近 120(即在双精度分辨率内),因此四舍五入为 120.0。但是,它总是略小于 120,因此显式楼层划分会将该数字截断为 119,然后才能规范化为 120.0。

一些证据:

>>> from decimal import Decimal
... print(6/Decimal(0.05))  # exactly approximate
... print(6/Decimal('0.05'))  # exact
119.9999999999999933386618522
1.2E+2

第一个数字是你第一次用6/0.05得到的数字,但119.9999999999999933386618522的数字四舍五入到最接近的双精度表示的数字,这是 120。人们可以很容易地证明这两个数字在双精度内确实是相同的:

>>> print(6/Decimal('0.05') - 6/Decimal(0.05))
6.6613381478E-15
>>> 120 - 6.6613381478E-15 == 120
True

以下是来自 MATLAB 的help mod

MOD(x,y) returns x - floor(x./y).*y if y ~= 0, carefully computed to
avoid rounding error. If y is not an integer and the quotient x./y is
within roundoff error of an integer, then n is that integer.

这表明,当x/y接近整数时,它首先被舍入,而不是像在python中那样被截断。因此,MATLAB 不遗余力地对浮点结果进行一些魔术。

最简单的解决方案是自己对数字进行四舍五入(除非您可以使用类似decimal.Decimal的东西,但这意味着您应该完全放弃原生双精度,包括文字),并以这种方式重现 MATLAB 的mod,假设这对您的用例有意义。

这是一个解决方法。它基本上将分母四舍五入到其str表示,并从那里进行整数算术:

import numpy as np
import decimal
def round_divmod(b,a):
n,d = np.frompyfunc(lambda x:decimal.Decimal(x).as_integer_ratio(),1,2)(a.astype('U'))
n,d = n.astype(int),d.astype(int)
q,r = np.divmod(b*d,n)
return q,r/d
a = np.round(np.linspace(0.05,1,20),2).reshape(4,5)
a
# array([[0.05, 0.1 , 0.15, 0.2 , 0.25],
#        [0.3 , 0.35, 0.4 , 0.45, 0.5 ],
#        [0.55, 0.6 , 0.65, 0.7 , 0.75],
#        [0.8 , 0.85, 0.9 , 0.95, 1.  ]])
round_divmod(6,a)
# (array([[120,  60,  40,  30,  24],
#        [ 20,  17,  15,  13,  12],
#        [ 10,  10,   9,   8,   8],
#        [  7,   7,   6,   6,   6]]), array([[0.  , 0.  , 0.  , 0.  , 0.  ],
#        [0.  , 0.05, 0.  , 0.15, 0.  ],
#        [0.5 , 0.  , 0.15, 0.4 , 0.  ],
#        [0.4 , 0.05, 0.6 , 0.3 , 0.  ]]))

最新更新