gpt4 book ai didi

c++ - 无法使用 中的 C/C++ nextafter/nexttoward 函数获取下一个 32 位浮点值

转载 作者:太空狗 更新时间:2023-10-29 20:13:42 26 4
gpt4 key购买 nike

使用 C 或 C++,我想在一个循环中递增所有可表示的 32 位 float 的范围,类似于您递增 32 位整数表示的所有不同值的方式。

类似于:对于( float f = FLOAT_MIN;f < MAX;f = Next_Float(f)){...}

我认为我可以使用标准数学库中的“nexttoward”或“nextafter”函数来完成该任务。见 http://www.cplusplus.com/reference/cmath/nextafter/

现在,当我在 Ubuntu 13.04 上使用 double 或长 double 测试“nexttoward”或“nextafter”函数并使用 g++ 4.7 进行编译时,我没有遇到任何问题。见测试代码:

#include <math.h>   
#include <iostream>
#include <iomanip>

int main ()
{
double f = 0.1;
for(int i = 0; i < 5; ++i)
{
//Marginally increment f in the upper direction.
f = nexttoward(f,999.999);
std::cout << std::setprecision(70) << f << std::endl;
std::cout << nexttoward(f,999.999) << std::endl;
}
return 0;
}

程序的浮点输出值按预期稳步增加:

ubuntu@ubuntu:~$ g++ -o temp ~/temp.cpp

ubuntu@ubuntu:~$ ./temp

0.100000000000000019428902930940239457413554191589355468750.1000000000000000333066907387546962127089500427246093750.1000000000000000333066907387546962127089500427246093750.100000000000000047184478546569152968004345893859863281250.100000000000000047184478546569152968004345893859863281250.10000000000000006106226635438360972329974174499511718750.10000000000000006106226635438360972329974174499511718750.100000000000000074940054162198066478595137596130371093750.100000000000000074940054162198066478595137596130371093750.100000000000000088817841970012523233890533447265625

ubuntu@ubuntu:~$

但是当我尝试使用 float 而不是 double 时,“nexttoward”和“nextafter”函数让我失望了——这些函数返回的值似乎比 32 位 float 更精确,当我将返回值分配给我的 32-位 float , float 保留其原始值而不是上升到下一个更高的值。查看示例代码和输出:

#include <math.h>    
#include <iostream>
#include <iomanip>

int main ()
{
float f = 0.1f;
for(int i = 0; i < 10; ++i)
{
//Marginally increment f in the upper direction.
f = nexttoward(f,999.999f);
std::cout << std::setprecision(70) << f << std::endl;
std::cout << nexttoward(f,999.999f) << std::endl;
}
return 0;
}

请注意,“nexttoward”的第二个输出值具有更高的精度,并且 f 保持相同的值:

ubuntu@ubuntu:~$ g++ -o temp ~/temp.cpp

ubuntu@ubuntu:~$ ./temp

0.1000000014901161193847656250.100000001490116133262553432814456755295395851135253906250.1000000014901161193847656250.100000001490116133262553432814456755295395851135253906250.1000000014901161193847656250.100000001490116133262553432814456755295395851135253906250.1000000014901161193847656250.100000001490116133262553432814456755295395851135253906250.1000000014901161193847656250.100000001490116133262553432814456755295395851135253906250.1000000014901161193847656250.100000001490116133262553432814456755295395851135253906250.1000000014901161193847656250.100000001490116133262553432814456755295395851135253906250.1000000014901161193847656250.100000001490116133262553432814456755295395851135253906250.1000000014901161193847656250.100000001490116133262553432814456755295395851135253906250.1000000014901161193847656250.10000000149011613326255343281445675529539585113525390625

我想递增所有 32 位浮点值,而不是所有 64 位 double 值 - 递增所有 double 值的时间太长。

如何解决此问题并实现一种高效、方便且可移植的方式来遍历 32 位浮点变量的范围?

最佳答案

nextafternexttoward函数接受 double 类型的参数并返回 double 类型的结果.

对于 float ,使用对应的nextafterfnexttowardf功能。

这是 <math.h> 中声明的几乎所有数学函数的通用规则.例如,有三个平方根函数:

  • sqrtf (对于 float)
  • sqrt (对于 double)
  • sqrtl (对于 long double)

(floatlong double 版本由 C99 添加,可能并非所有实现都支持。)

如果你对一个类型使用了错误的函数,编译器不会报错;它会悄悄地将参数转换为预期的类型,并根据您对它的处理来转换结果。

那是给 C 的。如果你使用 #include <cmath> , C++ 为类型 f 添加了数学函数的重载版本(没有 lfloat 后缀)和 long double .因此,如果您将代码编译为 C++,那么这些函数应该的行为符合您的预期。 (<math.h><cmath> 之间可能存在差异;无论如何,对于 C++,您应该使用后者。)

你的问题被标记为 C 和 C++,它们在这方面有显着差异。

(C99 还添加了一个 <tgmath.h> header ,提供特定于类型的宏,其行为类似于 C++ 的重载函数。)

关于c++ - 无法使用 <math.h> 中的 C/C++ nextafter/nexttoward 函数获取下一个 32 位浮点值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19885622/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com