我正在 cppreference 中查看这些相关的标准函数系列:std::round、std::floor和。std::ceilstd::trunc
有什么理由为什么std::round是唯一一个提供特定签名long并long long作为返回类型的吗?我正在努力思考除了历史之外的任何原因,但std::round最近才在 C++11 中添加了这一点。
这只是我的猜测,但我认为原因可能是,l和ll的版本可以使用rint和不同的floor舍入模式ceil来trunc实现。例如,可以这样实现:llfloor()
#include <cfenv>\n#include <cmath>\n#pragma STDC FENV_ACCESS ON\n\nlong long llfloor(double arg) {\n auto save_round = std::fegetround();\n std::fesetround(FE_DOWNWARD);\n auto ret = llrint(arg);\n std::fesetround(save_round);\n return ret;\n}\nRun Code Online (Sandbox Code Playgroud)\nl/ versions的一个很好的属性ll是,当结果超出结果类型的范围时,它们会引发FE_INVALID 异常。我们的llfloor()也这样做:
#include <iostream>\n#include <limits>\n\nint main() {\n double input = std::nextafter(std::numeric_limits<long long>::max(), INFINITY);\n std::cout << "input = " << std::fixed << input << "\\n";\n\n std::feclearexcept(FE_ALL_EXCEPT);\n auto result = llfloor(input);\n if (std::fetestexcept(FE_INVALID)) {\n std::cout <<"FE_INVALID was raised\\n";\n }\n std::cout << "result = " << result << "\\n";\n}\nRun Code Online (Sandbox Code Playgroud)\n输出是(或参见godbolt):
\ninput = 9223372036854777856.000000\nFE_INVALID was raised\nresult = -9223372036854775808\nRun Code Online (Sandbox Code Playgroud)\n您可能仍然会问“不能llround用 来实现llrint吗?”。事实证明不能。FE_TONEAREST 舍入模式对于中间情况舍入为均匀round,而远离零。
另请注意,编译器对访问或修改浮点环境的支持可能尚未完全实现:
\nmain.cpp:3: warning: ignoring \xe2\x80\x98#pragma STDC FENV_ACCESS\xe2\x80\x99 [-Wunknown-pragmas]\n 3 | #pragma STDC FENV_ACCESS ON\nRun Code Online (Sandbox Code Playgroud)\n(相关问题:两个浮点数相加)
\n| 归档时间: |
|
| 查看次数: |
377 次 |
| 最近记录: |