簡體   English   中英

numpy或python中的等效matlab函數mod

[英]Equivalent matlab function mod in numpy or python

我正在將一些代碼從Matlab轉換為Python。

在matlab中有函數mod ,它給出了模運算。

例如,以下示例顯示了matlab mod和等效numpy remainder操作之間的不同結果:

Matlab的:

>> mod(6, 0.05)

ans =

     0

NumPy的:

np.remainder(6, 0.05) 
0.04999999999999967

np.mod(6, 0.05)
0.04999999999999967

Python模運算符給出與numpy相同的結果。

6%0.05
0.04999999999999967

python中有沒有提供與Matlab相同的mod操作? 優選地,可以在numpy 2d / 3d陣列上操作。

numpy 文檔numpy.mod相當於matlab mod

這是問題的核心,在python中:

>>> 6/0.05 == 120
True

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

6/0.05的浮點結果足夠接近120(即在雙精度的分辨率內),它被舍入到120.0。 但是,它比120略小,因此明確的分區將在將其標准化為120.0之前將該數字截斷為119。

一些證據:

>>> 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這樣的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.  ]]))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM