【问题标题】:Stochastically rounding a float to an integer将浮点数随机四舍五入为整数
【发布时间】:2020-10-01 18:59:02
【问题描述】:

我想要一个函数(如果相关,则使用 Python 3.6+),它会以下列方式将浮点数随机四舍五入为整数:

给定一个实数x,让a = floor(x)b = ceil(x)。然后,编写一个函数s_int(),它将以b - x 的概率返回a,并以x - a 的概率返回b

例如,s_int(14.8) 应该在 20% 的时间返回 14,在剩余的 80% 的时间返回 15


这是我的尝试:

import math
from random import random

def s_int(x):
    a = math.floor(x)
    return a + ((x - a) > random())

它似乎适用于我能想到的所有情况:

In [2]: Counter(s_int(14.7) for _ in range(1000000))
Out[2]: Counter({14: 300510, 15: 699490})

In [3]: Counter(s_int(-14.7) for _ in range(1000000))
Out[3]: Counter({-15: 700133, -14: 299867})

In [4]: Counter(s_int(14) for _ in range(1000000))
Out[4]: Counter({14: 1000000})

In [5]: Counter(s_int(-14) for _ in range(1000000))
Out[5]: Counter({-14: 1000000})

In [6]: Counter(s_int(0) for _ in range(1000000))
Out[6]: Counter({0: 1000000})

这是我的问题:

  1. 有没有我认为这个函数不起作用的边缘情况?

  2. 还有其他更简单或更优雅的解决方案吗?

  3. 可以让它运行得更快吗?

【问题讨论】:

  • 这可能更适合codereview.stackexchange.com
  • @XYZT 我猜你是对的。
  • 应该是return a + ((x - a) >= random())random 包括 0.0 但不包括 1.0。 Python 的浮点数有 52 位尾数,因此天花板下的最大数字永远不会用您的方法输出地板。我有点认为你有 1 到 52 位的偏差。如果我是对的,你的火箭将与火星相距相当远。当然,如果你改变它,1.0 将每隔一段时间发出2。我要彻底放弃火星飞行了。
  • @tdelaney:Python 没有指定浮点格式,除非最近发生了变化。许多实现使用 IEEE-754 binary64。该格式的有效位,而不是尾数,有 53 位。 52 被编码在主要有效位字段中,1 被编码在指数字段中。对于 1 以下的最大可表示数(称为 g),使用 > 产生的结果永远不会是上限。但是,对于大于 1 的上限,上限下的最大可表示数字有时会返回上限,因为 x-floor(x) 小于 g,因为 x 处的 ULP 更大。
  • @tdelaney: (x - a) > random() 还具有对精确整数执行正确操作的优点:如果x 是精确整数,x - a 将精确为零,所以@987654343 @ 永远不会是真的,我们将永远“四舍五入”到 x 本身。用>= 代替>x = 14.0 有可能被四舍五入到15.0

标签: python python-3.x floating-point integer rounding


【解决方案1】:
  1. 我认为没有极端情况
  2. 尝试使用 numpy
import numpy as np
def s_int(x):
    a = np.floor(x)
    b = a + 1
    return (np.random.choice([a, b], p=[b - x, x - a]))
  1. 我认为这是一个 O(1) 操作。不会走得更快。

【讨论】:

  • np.floor 不返回整数,而是返回浮点数。
  • 另外,它的速度非常慢 50 倍
  • 在我的笔记本电脑上,对 10^6 个样本使用 timeit + rd.random() 需要 7 毫秒,>>> print(timeit.timeit(str(s_int(3 + rd.random())) , number=1000000))
  • 好的,现在我看到您真的在寻找速度,而不仅仅是实现!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-13
  • 1970-01-01
  • 1970-01-01
  • 2015-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多