【问题标题】:generate random numbers truncated to 2 decimal places生成截断到小数点后 2 位的随机数
【发布时间】:2013-05-10 21:11:38
【问题描述】:

我想生成 0 到 0.5 之间的均匀分布随机数,但截断到小数点后 2 位。

没有截断,我知道这是由

import numpy as np
rs = np.random.RandomState(123456)
set = rs.uniform(size=(50,1))*0.5

任何人都可以帮助我就如何生成高达 2 d.p 的随机数提供建议。只要?谢谢!

【问题讨论】:

  • 你知道小数 0.1 不存在作为float吗?
  • 是的,我相信我应该澄清一下,我希望它四舍五入到 2 个有效数字。 (在数值精度范围内)
  • @mtigger:我认为你没有抓住重点。如果您将0.10 舍入为 2 个有效数字并将其存储在 float(或 numpy f8)中,您将得到 0.100000000000000005551115。而下一个较小的float 小于0.10。 IEEE double 中没有等于 0.10 的值。
  • @mtigger:嗯,那是不可能。 0.10 不能存储在float 中。它总是一个近似值。在 Python 2.6 中,您可以看到这一点(在更高版本中它被隐藏但仍然存在):在提示符处键入 .1 并看到它表示为 0.10000000000000001(这仍然只是一个近似值)。
  • 生成随机整数并用隐式移位 100 解释它们。或者使用十进制数据类型。

标签: python random numpy


【解决方案1】:

float 不能被截断(或四舍五入)为 2 位十进制数字,因为有许多具有 2 位十进制数字的值不能完全表示为 IEEE 双精度。

如果你真的想要你所说的,你需要使用精确的类型,比如Decimal。

当然,这样做也有缺点——对于numpy 用户来说,最明显的缺点是您必须使用dtype=object,这会影响所有的紧凑性和性能。

但这是真正做到你所要求的唯一方法。

最有可能的是,您实际上想要做的是 Joran Beasley 的答案(不要截断它们,并在打印输出时四舍五入)或类似于 Lauritz V. Thaulow 的答案(获取最接近的近似值,然后在任何地方使用显式 epsilon 检查)。

或者,您可以执行隐式定点算术,正如 David Heffernan 在评论中建议的那样:生成 0 到 50 之间的随机整数,将它们保留为 numpy 中的整数,并将它们格式化为定点小数和/或必要时转换为Decimal(例如,用于打印结果)。这为您提供了 Decimal 的所有优势,而无需任何成本……尽管它确实打开了一个明显的窗口,通过忘记在某处移动 2 个位置来创建新错误。

【讨论】:

【解决方案2】:

小数不会被截断到小数点后 2 位……但是它们的字符串表示可能

import numpy as np
rs = np.random.RandomState(123456)
set = rs.uniform(size=(50,1))*0.5

print ["%0.2d"%val for val in set]

【讨论】:

  • Decimals 可以截断到小数点后两位; floats 不能。
  • meh 语义:P(但我知道 Decimal 是一种精确的表示类型:P)
【解决方案3】:

这个怎么样?

np.random.randint(0, 50, size=(50,1)).astype("float") / 100

即创建 0 到 50 之间的随机整数,然后除以 100。

编辑:

正如 cmets 中明确指出的那样,由于内存中浮点表示的性质,这不会为您提供精确两位小数。看起来您的数组中有确切的浮点数 0.1,但它绝对不是完全是 0.1。但它非常接近,您可以改为使用“double”数据类型来使其更接近。

您可以通过将数字保留为整数来推迟这个问题,并记住在使用它们时它们要除以​​ 100。

hundreds = random.randint(0, 50, size=(50, 1))

那么至少直到最后一分钟才会发生舍入(或者可能根本不会发生,如果等式的分子是分母的倍数)。

【讨论】:

  • @Joran 哇,这是快速反馈。你测试过这个吗?我的测试都只返回两位或一位小数。
  • @LauritzV.Thaulow:有许多带有两位小数的值不能完全表示为浮点数(IEEE 双精度)。所以,你可能会得到最接近你想要的值的浮点数,它甚至可能是你想要的值 repr 和 str……但是当你用它做算术,或者只是将它与 == 比较时,它可能不是你想要的价值。如果您真的想要两位小数,则必须使用精确精度类型,例如 Decimal。
  • 另外,这并不能解决问题,因为从正态分布中采样不会生成整数(尽管您可以对分布进行四舍五入)。沿着这些思路解决的更一般的想法是(对于 x~Norm(params)),int(round(x*100))/100。
【解决方案4】:

我设法找到了另一种选择:

import numpy as np
rs = np.random.RandomState(123456)
set = rs.uniform(size=(50,2))
for i in range(50):
    for j in range(2):
        set[i,j] = round(set[i,j],2)

【讨论】:

  • 那为什么不直接使用np.around(rs.uniform(size=(50,2)) * 0.5, decimals=2)呢?如the docs 所述,它更快,工作方式相同,并且具有与我的解决方案相同的技术缺陷:由于 IEEE 浮点标准中小数部分的不精确表示,结果也可能令人惊讶 i>.
猜你喜欢
  • 1970-01-01
  • 2014-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-25
  • 2019-04-23
  • 2023-04-08
  • 1970-01-01
相关资源
最近更新 更多