简体   繁体   English

Python 浮点数可以被另一个浮点数整除

[英]Python floating point is divisible by another floating point

Does anyone know a good way in Python to check if a number is divisible by another in floating point in python?有谁知道在 Python 中检查一个数字是否可以在 python 中的浮点数中被另一个数字整除的好方法?

The first thing I tried was...我尝试的第一件事是...

3.5 % 0.1 == 0.0

But this returns False so then maybe但这会返回False所以也许

3.5 % 0.1 >= 1e-6 

But also False ... bummer... it turns out that但也是False ......真可惜......事实证明

3.5 % 0.1
>> 0.099999999924

So then this works:那么这有效:

LAMBDA = 1e-9
def is_divisible_by(x, y):
   m = x % y
   dy = abs(y - m)
   return m < LAMBDA or dy < LAMBDA

is_divisible_by(3.5, 0.1)

But this seems dangerous because I have to pick a LAMBDA.但这似乎很危险,因为我必须选择 LAMBDA。 What about if y = LAMBDA / 2 ...如果y = LAMBDA / 2 ...

is_divisible_by(LAMBDA/2, (LAMBDA/2) + 1e-10)
>>> True

So then那么那么

  def is_divisible_by(x, y):
      l = y * 1e-2
      m = x % y
      dy = abs(y - m)
      return m < l or dy < l

  is_divisible_by(3.5 * 1e-10, 0.1 * 1e-10)
  >>> True

  is_divisible_by(0.21, 0.211)
  >>> True
  

Bummer.真可惜。

Is there anyway to solve this without going down a massive rabbit hole?有没有办法在不掉进一个巨大的兔子洞的情况下解决这个问题?

Depending on the source of your floating point numbers, the decimal module might be useful.根据浮点数的来源, decimal模块可能有用。

>>> import decimal
>>> decimal.Decimal("3.5") % decimal.Decimal("0.1")
Decimal('0.0')

floating point numbers are "fuzzy".浮点数是“模糊的”。 A good high-level mental model for floating point numbers is that they represent a small range of numbers (eg 1.5 really means some number between 1.4999 and 1.5002).浮点数的一个很好的高级心智模型是它们代表一个小范围的数字(例如,1.5 真的意味着 1.4999 和 1.5002 之间的某个数字)。 Because of this, there is not good way to check if one is divisible by another.因此,没有很好的方法来检查一个是否可以被另一个整除。 Instead, to check if non-integer numbers are divisible by each other, you might want to use rational-type numbers .相反,要检查非整数是否可以相互整除,您可能需要使用有理数类型 In python, there's a module for this, called Fraction.在 python 中,有一个模块,叫做 Fraction。 You can use it like this你可以像这样使用它

from fractions import Fraction
a = Fraction(35,10) # 3.5
b = Fraction(1,10) # .1
a%b # evaluates to Fraction(0, 1)

Another answer mentioned the decimal python module.另一个答案提到了十进制 python 模块。 Fraction and decimal are interoperable.分数和小数是可以互操作的。

from fractions import Fraction
from decimal import Decimal
a = Fraction(Decimal('3.5')) # 3.5
b = Fraction(Decimal('0.1)) # 0.1
a%b # evaluates to Fraction(0, 1)

I'm going to advocate for using Fraction as it is a bit more flexible我将提倡使用 Fraction,因为它更灵活一些

from fractions import Fraction
from decimal import Decimal
c = Decimal('1')
d = Decimal('.3')
c/d  # evaluates to Decimal('3.333333333333333333333333333')
c/d*d  # evaluates to Decimal('0.9999999999999999999999999999')
c = Fraction(c)
d = Fraction(d)
c/d # evaluates to Fraction(10, 3)
c/d*d # evaluates to Fraction(1, 1)

A potential solution is to multiply both floats by a "sufficiently large" scaling factor and then cast (round) to integers.一个潜在的解决方案是将两个浮点数乘以“足够大”的比例因子,然后将其转换为整数。

def check_floats_divisible(x: float, y: float, scaling_factor: float = 1e6):
    scaled_x = int(x * scaling_factor)
    scaled_y = int(y * scaling_factor)
    
    return (scaled_x % scaled_y) == 0

check_floats_divisible(3.5, 0.1)
>>> True

Notes:笔记:

  1. "Sufficiently large" may not be appropriate for your use case. “足够大”可能不适合您的用例。 It works well if, for example your two floats were time durations in seconds, and a particular time precision was acceptable in your use-case (eg microseconds).例如,如果您的两个浮点数是以秒为单位的持续时间,并且在您的用例中可以接受特定的时间精度(例如微秒),那么它会很好地工作。
  2. Need to be careful your scaling is sufficient to ensure the denominator is never zero after conversion to int.需要注意您的缩放比例足以确保在转换为 int 后分母永远不会为零。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM