python-3.x - 如何安全地从 float64 圆形和钳位到 int64?
问题描述
这个问题是关于 python/numpy 的,但它也可能适用于其他语言。
如何改进以下代码以在转换期间将大浮点值安全地钳制为最大 int64 值?(理想情况下,它应该仍然有效。)
import numpy as np
def int64_from_clipped_float64(x, dtype=np.int64):
x = np.round(x)
x = np.clip(x, np.iinfo(dtype).min, np.iinfo(dtype).max)
# The problem is that np.iinfo(dtype).max is imprecisely approximated as a
# float64, and the approximation leads to overflow in the conversion.
return x.astype(dtype)
for x in [-3.6, 0.4, 1.7, 1e18, 1e25]:
x = np.array(x, dtype=np.float64)
print(f'x = {x:<10} result = {int64_from_clipped_float64(x)}')
# x = -3.6 result = -4
# x = 0.4 result = 0
# x = 1.7 result = 2
# x = 1e+18 result = 1000000000000000000
# x = 1e+25 result = -9223372036854775808
解决方案
问题是最大np.int64
的是 2 63 - 1,不能用浮点数表示。同样的问题不会发生在另一端,因为 -2 63是完全可表示的。
所以在浮点空间(用于检测)和整数空间(用于校正)中进行剪裁一半:
def int64_from_clipped_float64(x, dtype=np.int64):
assert x.dtype == np.float64
limits = np.iinfo(dtype)
too_small = x <= np.float64(limits.min)
too_large = x >= np.float64(limits.max)
ix = x.astype(dtype)
ix[too_small] = limits.min
ix[too_large] = limits.max
return ix
推荐阅读
- javascript - javascript - Uncaught (in promise) TypeError: e.iterator is not a function。如何解决此类错误?
- angular - 由于地理围栏插件,Ionic 构建失败
- oracle - 如何从不同模式的触发器调用另一个模式的过程
- javascript - 使用 angular 8 生成 pwa 到 apk 或 ios
- swift - Combine 如何知道 ObservableObject 实际发生了变化
- flutter - 带有“:”的命名构造函数
- tizen - 蒂岑。如何更新页面内容 CircleScrollView 的子项
- postgresql - 如何在不使用 ORM 的情况下将 Nestjs 应用程序连接到 postgreSQL?
- angular - 如何按日期将数组排序为角度?
- html - 仅为部分文本添加单个边框