AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 79334260
Accepted
Shantanu Gontia
Shantanu Gontia
Asked: 2025-01-07 04:29:30 +0800 CST2025-01-07 04:29:30 +0800 CST 2025-01-07 04:29:30 +0800 CST

当结果低于正常值时,Numpy Float 到 HalfFloat 转换 RNE

  • 772

我试图了解 NumPy 如何实现四舍五入到最接近的数,即使在转换为较低精度格式时也是如此,在本例中为 Float32 到 Float16,具体来说,当数字在 Float32 中是正常的,但在 Float16 中四舍五入为低于正常值时。

代码链接: https ://github.com/numpy/numpy/blob/13a5c4e569269aa4da6784e2ba83107b53f73bc9/numpy/core/src/npymath/halffloat.c#L244-L365

我的理解如下,

在 float32 中,数字有位

31 三十 二十九 二十八 二十七 二十六 二十五 24 23 22 21 20 19 18 17 16 15 14 十三 12 11 10 9 8 7 6 5 4 3 2 1 0
s e0 e1 e2 e3 e4 e5 e6 e7 m0 米1 平方米 米3 米4 m5 米6 m7 M8 m9 m10 m11 m12 m13 m14 m15 m16 m17 m18 m19 m20 m21 m22
        /*
         * If the last bit in the half significand is 0 (already even), and
         * the remaining bit pattern is 1000...0, then we do not add one
         * to the bit after the half significand. However, the (113 - f_exp)
         * shift can lose up to 11 bits, so the || checks them in the original.
         * In all other cases, we can just add one.
         */
        if (((f_sig&0x00003fffu) != 0x00001000u) || (f&0x000007ffu)) {m
            f_sig += 0x00001000u;
        }

上述代码用于打破最接近偶数的平局。我不明白为什么在逻辑或的第二部分,我们对0x0000'07ffu(位 m12-m22) 进行按位与,而不是0x0000'ffffu(m11-m22) 进行按位与。

一旦我们将尾数位对齐为 float16 的亚正规格式(这是此段代码之前的位移所做的),在上面的 float32 数字表示中,我们就可以m10决定m22要舍入的方向。

我的理解是,OR 的第二部分检查数字是否大于中间点,如果是,则将半有效数字位加一。但对于原始数字,它不是只检查中间点以上的数字子集吗?在 float16 数字中,m9 将是最后一个要保留的精度。因此,如果满足以下条件,我们将向上舍入:

  1. m9 为 1,m10 为 1,m11-m22 均为 0(或的第一部分)

  2. m10 为 1,m11-m22 中至少有一个为 1(将数字置于中间点以上)

  3. 如果 m11-m22 中任何一个为 1,则可以通过将 1 添加到 m10 来简化。如果 m10 已经为 1,则添加将影响到 m9,否则将不受影响。但是,在 NumPy 代码的情况下,检查的位是 m12-m22。

我不确定我遗漏了什么。这是一个特殊情况吗?

我期望位 m11-m22 能够决定是否加 1 以及是否加 m12-m22。

numpy
  • 1 1 个回答
  • 41 Views

1 个回答

  • Voted
  1. Best Answer
    Eric Postpischil
    2025-01-07T06:11:29+08:002025-01-07T06:11:29+08:00

    f_sig包含一个为 binary16 结果准备的有效数字。(binary16是 IEEE-754 中对某些人称之为“半精度”浮点格式的名称。)此时,代码需要位 22:13 中的有效数字位,因为稍后要将它们再移动 13 位,将其放入 9:0。为此做准备,它根据指数移动了位。这会将一些位移出f_sig。

    现在它要测试新有效数字的低位(现在在位 13)是否为 0,有效数字以下的最高位(在位 12)是否为 1,并且所有剩余位是否为 0。其中一些剩余位位于 的位 11:0 中f_sig。但其中一些可能已经消失。根据指数的移位将其中一些移出。因此,要测试这些位是否为 0,我们在 中的原始有效数字中查看它们f。

    由于指数移位最多移出 11 位,我们只需查看 的低 11 位f。原始有效数字的其他位仍然存在于 中f_sig。

    因此,在 中(f_sig&0x00003fffu) != 0x00001000u) || (f&0x000007ffu), 的左操作数||测试 中的原始有效位f_sig,而 的右操作数测试 中的原始有效位f。可能存在一些重叠;后者可能会测试 中的某些位f_sig,但这并不重要。

    我的理解是,“或”的第二部分检查数字是否大于一半点,如果是,则在半有效数字位上加一。

    不,它没有检查这一点。当且仅当尾部不正好是新有效数字的最低有效位 (LSB) 的 ½ 或最低有效位为 1 时,测试才为真。

    理由如下:

    • 受控语句f_sig += 0x00001000u;会添加 ½ LSB,随后在 LSB ( f_sig >> 13) 处截断有效数字。这在大多数情况下可提供所需的舍入:向小于 ½ 的尾随部分添加 ½ 不会进位,向大于 ½ 的尾随部分添加 ½ 会进位。
    • 此外,如果尾部正好是 ½ 并且我们添加 ½,则加法会进位,这是当 LSB 的低位为 1 时所需的行为。
    • 因此,我们不想进行这种加法的唯一情况是当尾随部分正好是 ½ 并且 LSB 的低位为 0 时。
    • 2

相关问题

  • 如何按特定键值“批量”排序张量?

  • Jupyter Notebook 查找矩阵行列式的根时出现弃用警告

  • 如何沿轴连接张量的内部矩阵?

  • 在 numpy 文档中输入 i4 和 S8 的升级规则

  • 使用索引数组将 numpy 数组广播为更大尺寸的数组

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    重新格式化数字,在固定位置插入分隔符

    • 6 个回答
  • Marko Smith

    为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会?

    • 2 个回答
  • Marko Smith

    VScode 自动卸载扩展的问题(Material 主题)

    • 2 个回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Martin Hope
    Fantastic Mr Fox msvc std::vector 实现中仅不接受可复制类型 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant 使用 chrono 查找下一个工作日 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor 构造函数的成员初始化程序可以包含另一个成员的初始化吗? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský 为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul C++20 是否进行了更改,允许从已知绑定数组“type(&)[N]”转换为未知绑定数组“type(&)[]”? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann 为什么 {2,3,10} 和 {x,3,10} (x=2) 的顺序不同? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve