为什么std::round的返回值类型不是整数?

4
我对将float/double变量四舍五入到最近的整数有些困惑。在谷歌搜索时,我发现了cppreference关于四舍五入的页面this。在该页面上,它说:
float       round ( float arg );         // (1)
float       roundf( float arg );         // (2)
double      round ( double arg );        // (3)
long double round ( long double arg );   // (4)
double      round ( IntegralType arg );  // (5)

在这里,我不明白为什么返回值类型是floatdoublelong double?例如,如果我有一个变量float x2.5 <= x < 3.5,那么它的四舍五入值是3。这可以用一个int来表示,对吗?那么,为什么std::round的返回值类型不是int(或long int用于long double)呢?

在该页面上,还写道:

1-5) 计算最接近 arg(以浮点格式表示)的整数值,四舍五入到远离零的一侧,而不考虑当前的舍入模式。

那么,"integer value to arg (in floating-point format)" 究竟是什么意思?


为了理解这个 std::round,我进行了一个小实验:
int main(int argc, char const *argv[]) {
    float var               = 3.14;
    int   rounded_var_int   = std::round(var);
    float rounded_var_float = std::round(var);

    std::cout << rounded_var_int << ", " << rounded_var_float << std::endl;  // 3, 3
    
    return 0;
}

然而,这让我更加困惑,因为一切都运行得很好。
所以,最后一个问题是:
在上面的代码中,int rounded_var_int = std::round(var) 是可以的,还是需要显式地将其转换为 int,例如 int rounded_var_int = static_cast<int>(std::round(var)),以避免任何潜在的错误?

你可以使用std::roundl(或者也许是std::roundll)来实现。 - Paul Sanders
5
内置整数类型无法存储10^200 - NathanOliver
对于你的第二个问题:没问题。该值只是被截断了。 - The Coding Fox
@SolvedGames 如果std::round的结果足够大,在将其截断为int时,是否会出现浮点错误并使您得到比预期少1的结果? - Paul Sanders
为了避免任何潜在的错误,你需要对浮点函数完全信任,以便百分之百地得到所需的结果,除非你可以接受那些看似“不正常”的值。 - PaulMcKenzie
1
如果您有一个浮点值,并且想要将其四舍五入,而该值保证适合整数类型,并且您将使用结果作为整数,则是的,round函数返回整数类型会很方便。但这不是一般情况,将结果转换为整数类型是您不想总是付出的额外成本(特别是如果您打算再次转换为浮点类型)。如果您想要这样做,可以简单地将其转换为整数类型以进行截断,或者对您的值+0.5执行相同操作以进行四舍五入,或者转换std::round的结果。 - François Andrieux
1个回答

5
为什么std::round的返回值类型不是整数?
因为浮点类型的可表示范围通常超过了基本整数类型的范围,这些整数类型无法表示所有可能的返回值。
除了超出整数类型范围的有限舍入值之外,其他有问题的值还包括无穷大、非数值和负零,这些值返回时不做改变。
舍入值为3。那么只用int就可以表示吗?
可以用int来表示这个值。但是,只能表示其中一个或一些值是不够的。返回类型应该能够表示所有的舍入值。而使用int通常无法达到这个目标。
在上面的代码中,int rounded_var_int = std::round(var) 就足够了吗?还是需要显式地将它强制转换为int,例如 int rounded_var_int = static_cast(std::round(var)) ,以避免任何潜在的错误?
浮点类型隐式转换为整数类型。隐式转换的结果与静态转换的结果相同。
这是一个缩小转换。无论是隐式还是显式转换都不安全,因为如果浮点值超出了可表示范围,程序的行为就是未定义的。但是,如果值是可表示的,那么转换后的值将保持不变,两种转换都是安全的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接