为啥 std::round 提供返回 long 和 long long 的版本,而 std::floor、std::ceil、std::trunc 不提供?
Posted
技术标签:
【中文标题】为啥 std::round 提供返回 long 和 long long 的版本,而 std::floor、std::ceil、std::trunc 不提供?【英文标题】:Why does std::round offer versions returning long and long long while std::floor, std::ceil, std::trunc don't?为什么 std::round 提供返回 long 和 long long 的版本,而 std::floor、std::ceil、std::trunc 不提供? 【发布时间】:2021-12-17 04:53:53 【问题描述】:我在 cppreference 中查看了这些相关的标准函数系列:std::round
、std::floor
、std::ceil
和 std::trunc
。
为什么std::round
是唯一一个为long
和long long
提供特定签名作为返回类型的人?除了历史原因,我很难想出任何原因,但最近 C++11 中添加了 std::round
。
【问题讨论】:
This isn't 100% a duplicate, but it answers your question。 (“std::floor
的返回值”的第一个谷歌结果)
返回整数没有意义。 std::round
只是出于某种原因。
@asynts 这是一个有趣的阅读,但它没有回答我的问题,我会想象问题中突出显示的相同限制将适用于 std::round,但不知何故标准库提供了特定的它的功能,而不是地板。
很可能是因为 c 有 exact same set of functions,但有趣的是知道为什么 c 没有为 ceil
/ floor
/ @ 添加 long
/ long long
版本987654341@.
@ALX23z std::floor
你的意思是std::trunc
,对吧? :-) 不同之处在于,使用强制转换可以溢出,即 UB,而使用 std::trunc
则不能。
【参考方案1】:
这只是我的猜测,但我认为原因可能是,floor
、ceil
和trunc
的l
和ll
版本可以使用rint 和不同的rounding modes 来实现。例如,llfloor()
可以这样实现:
#include <cfenv>
#include <cmath>
#pragma STDC FENV_ACCESS ON
long long llfloor(double arg)
auto save_round = std::fegetround();
std::fesetround(FE_DOWNWARD);
auto ret = llrint(arg);
std::fesetround(save_round);
return ret;
l
/ll
版本的一个很好的特性是,当结果超出结果类型的范围时,它们会引发 FE_INVALID exception。我们的llfloor()
也是这样做的:
#include <iostream>
#include <limits>
int main()
double input = std::nextafter(std::numeric_limits<long long>::max(), INFINITY);
std::cout << "input = " << std::fixed << input << "\n";
std::feclearexcept(FE_ALL_EXCEPT);
auto result = llfloor(input);
if (std::fetestexcept(FE_INVALID))
std::cout <<"FE_INVALID was raised\n";
std::cout << "result = " << result << "\n";
输出是(或参见godbolt):
input = 9223372036854777856.000000
FE_INVALID was raised
result = -9223372036854775808
您可能还在问“不能用llrint
实现llround
吗?”。事实证明它不能。 FE_TONEAREST 舍入模式对中途情况执行 rounding to even,而 round
执行远离零的情况。
另外请注意,编译器对访问或修改 floating point environment 的支持可能尚未完全实现:
main.cpp:3: warning: ignoring ‘#pragma STDC FENV_ACCESS’ [-Wunknown-pragmas]
3 | #pragma STDC FENV_ACCESS ON
(相关问题:Adding two floating-point numbers)
【讨论】:
以上是关于为啥 std::round 提供返回 long 和 long long 的版本,而 std::floor、std::ceil、std::trunc 不提供?的主要内容,如果未能解决你的问题,请参考以下文章
ajax获取java后台的返回值,long的值为啥会四舍五入解决办法
为啥Java中的BitSet使用long数组做内部存储,而不使用int数组...
python 对于提供给Google的位置,返回lat long