微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

std :: min / float monoid的标识元素

如何解决std :: min / float monoid的标识元素

this(非常有趣)中,演讲者提出了一个问题:

float / std :: min id半群的e值是什么。

换句话说:由标准C ++浮点数和std :: min操作组成的monoid的标识元素是什么?演讲者说答案很“有趣”。

我认为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时,总是会得到left参数。无限答案是正确的答案还是我错过了什么?

编辑:我似乎错过了一些东西。这个:

  cout << std::min(nan,nan) << "\n";

打印:

nan
inf

因此,对于NaN假名,我们会根据参数的顺序获得不同的答案。

解决方法

显然,在仿射扩展的实数(即,包括+/- inf但不包括NaN)上的min是一个类半群。

但是,将任何内容与NaN进行比较的结果是不是否,而是“ unordered”。这意味着<只是float上的偏序,因此std::min(根据<定义)不是一个等分线。

IEEE 754中有一个totalOrder谓词-尽管我完全不知道它在C ++中是如何公开的。我们可以这样写而不是min来写自己的<,而形成一个类半身像……但不是std::min


为进行确认,我们可以在godbolt上编译您的代码的变体,以查看在实践中如何实现该代码:

  • 使用comiss完成比较,可能会得出结果

      UNORDERED: ZF,PF,CF←111;
      GREATER_THAN: ZF,CF←000;
      LESS_THAN: ZF,CF←001;
      EQUAL: ZF,CF←100;
    

    并指定

    如果任一源操作数是NaN(QNaN或SNaN),则返回无序结果。

  • 使用jbe完成分支,

    如果小于或等于CF = 1或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>不具有关联性,因此也不是monoid。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。