c++ - std::min/float monoid 的标识元素

标签 c++ monoids

this (很有趣)说话者提出一个问题:

What is the e value for the float/std::min monoid.


换句话说:由标准 C++ 浮点数和 std::min 操作组成的幺半群的单位元素是什么?演讲者说答案是“有趣的”。
我认为std::numeric_limits<float>::infinity()应该是答案,如代码所示:
  const auto max = numeric_limits<float>::max();
  const auto min = numeric_limits<float>::min();
  const auto nan = numeric_limits<float>::signaling_NaN();
  const auto nan2 = numeric_limits<float>::quiet_NaN();
  const auto inf = numeric_limits<float>::infinity();
  const auto minus_inf = -inf;
  cout << std::min(max, inf) << "\n";
  cout << std::min(min, inf) << "\n";
  cout << std::min(nan, inf) << "\n";
  cout << std::min(nan2, inf) << "\n";
  cout << std::min(inf, inf) << "\n";
  cout << std::min(minus_inf, inf) << "\n";
哪个打印:
3.40282e+38
1.17549e-38
nan
nan
inf
-inf
在测试中调用 std::min 时,我们总是得到左参数。无穷大是正确答案还是我错过了什么?
编辑:我似乎错过了一些东西。这个:
  cout << std::min(nan, inf) << "\n";
  cout << std::min(inf, nan) << "\n";
打印:
nan
inf
因此,在 NaN 恶作剧的情况下,我们会根据参数的顺序得到不同的答案。

最佳答案

min显然是真的在仿射扩展实数上(即,包括 +/-inf 但不包括 NaN)是幺半群。
但是,将任何内容与 NaN 进行比较的结果不是假的,而是“unordered”。这意味着 <只是 float 的部分订单, 和 std::min (根据 < 定义)因此不是幺半群。
IEEE 754 中有一个 totalOrder谓词 - 虽然我不知道它是如何在 C++ 中公开的,如果有的话。我们可以自己写 min在这方面而不是 < ,这将形成幺半群......但它不会是 std::min .

为了确认,我们可以在 godbolt 上编译您的代码的变体,看看这在实践中是如何实现的:

  • 比较是通过 comiss 完成的, 有可能的结果
      UNORDERED: ZF,PF,CF←111;
      GREATER_THAN: ZF,PF,CF←000;
      LESS_THAN: ZF,PF,CF←001;
      EQUAL: ZF,PF,CF←100;
    
    并指定

    The unordered result is returned if either source operand is a NaN (QNaN or SNaN).


  • 分支完成 jbe ,这将

    Jump short if below or equal (CF=1 or ZF=1).



  • 您可以看到 UNORDERED 结果实际上被此条件分支视为小于和等于。
    因此,假设这是 IEEE 754 提到的无序比较的合法模型,则应该允许同时具有
    min(min(+inf, NaN), -inf) =
    min(+inf, -inf)           = -inf
    
    min(+inf, min(NaN, -inf)) =
    min(+inf, NaN)            = +inf
    
    这意味着 min<float>不是结合的,因此不是幺半群。

    关于c++ - std::min/float monoid 的标识元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64210645/

    相关文章:

    c++ - C++ 中的 PDF 解析 (PoDoFo)

    c++ - 使用 EvtSetChannelConfigProperty() 函数时出现访问冲突错误

    C++ 类默认构造函数

    sorting - 你能把冒泡排序表述为一个幺半群或半群吗?

    haskell - 如何解决Haskell代码错误“"<>'不是类 `Monoid'的(可见)方法”?

    新类型的 Haskell Monoid 实例问题

    c++ - 为什么在 C++ 中声明一个全局数组时,它可以给出的大小比在 main 中声明的要大

    c++ - 为什么GDB尝试列出不存在的 header ?

    string - 在 Haskell 中 Maybe String 和 Maybe Int 都是幺半群吗?

    haskell - 一个基本的 Monoid 定义给出 "No instance for (Semigroup MyMonoid) arising from the superclasses of an instance declaration"