首页 > 解决方案 > Python对np数组取模

问题描述

另一个问题Python modulo on floats描述了为什么 Python 的 modulo 对浮点数有问题(我也知道计算机数字不是本文所涵盖的数字,尤其是 3 的倍数)。但是,我在模数方面遇到了类似但不同的问题,并且接受的答案不起作用。

这是 MacBook Pro 上 Python 3.7.1 中的可重现示例:

import numpy as np
x = np.array([2.012, 2.012 *2, 2.012 *3, 2.012 *4, 2.012 *5, 2.012 *6])
x % 2.012
# array([0.0000000e+00, 0.0000000e+00, 2.0120000e+00, 0.0000000e+00,
#        4.4408921e-16, 2.0120000e+00])

如果我尝试接受的答案,我仍然会遇到同样的问题:

from decimal import Decimal
Decimal(3*2.012) % Decimal(2.012)
# Decimal('2.011999999999999566568931186')

我的具体问题:如何计算模数并为我的示例等系列取零?

根据反馈编辑:

作为一个具体的例子,如果我的数据看起来像这样,我该如何做模运算符(具体值将从实际数据中读取):

## X is read in from real data
x = np.array([2.012, 4.024, 6.036, 8.048, 1, 2, 3, 1.2, 1.3, 1.4, 1, 5, 6, 2.012, 2.012, 2.012])
[D(x) % D(frequency) for x in detections]
#[Decimal('0E-51'), Decimal('0E-51'), Decimal('2.011999999999999566568931186'), Decimal('0E-51'), Decimal('1.000000000000000000000000000'), Decimal('2.000000000000000000000000000'), Decimal('0.9879999999999999893418589636'), Decimal('1.199999999999999955591079015'), Decimal('1.300000000000000044408920985'), Decimal('1.399999999999999911182158030'), Decimal('1.000000000000000000000000000'), Decimal('0.9759999999999999786837179272'), Decimal('1.975999999999999978683717927'), Decimal('0E-51'), Decimal('0E-51'), Decimal('0E-51')]

标签: pythonnumpyfloating-pointmodulo

解决方案


In [6]: from decimal import Decimal as D
In [7]: D('3')*D('2.012') % D('2.012')
Out[7]: Decimal('0.000')

Python 在将参数传递给函数(或可调用对象,例如Decimal)之前评估参数。因此,如果要保留十进制值,则必须避免评估浮点数。 3*2.012因此,始终将小数的字符串表示形式传递给Decimal而不是浮点数。


如果您有一个包含

2.012, 4.024, 6.036, 8.048, 1, 2, 3, 1.2, 1.3, 1.4, 1, 5, 6, 2.012, 2.012, 2.012

然后将值加载为字符串并将它们转换Decimal为,以避免将它们表示为浮点数。

import csv
from decimal import Decimal as D
freq = D('2.012')
with open('data', 'r') as f:
    reader = csv.reader(f)
    X = [D(item) for item in next(reader)]
    print([xi % freq for xi in X])

产量

[Decimal('0.000'), Decimal('0.000'), Decimal('0.000'), Decimal('0.000'), Decimal('1.000'), Decimal('2.000'), Decimal('0.988'), Decimal('1.200'), Decimal('1.300'), Decimal('1.400'), Decimal('1.000'), Decimal('0.976'), Decimal('1.976'), Decimal('0.000'), Decimal('0.000'), Decimal('0.000')]

由于 Decimals 不是 NumPy/Pandas 原生 dtype,因此将它们存储在 NumPy 数组或 Pandas Series 中需要通用objectdtype。NumPy/Pandas 不为小数提供任何矢量化运算,因此在此处使用 NumPy/Pandas 不会提高性能。


推荐阅读