首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >可由小于1的浮点类型表示的最大值。

可由小于1的浮点类型表示的最大值。
EN

Stack Overflow用户
提问于 2022-03-07 07:35:25
回答 3查看 1.9K关注 0票数 24

是否有一种方法可以获得比float小的浮点类型1表示的最大值。

我有见以下定义

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static const double DoubleOneMinusEpsilon = 0x1.fffffffffffffp-1;
static const float FloatOneMinusEpsilon = 0x1.fffffep-1;

但这就是我们应该如何定义这些价值观吗?

根据标准,std::numeric_limits<T>::epsilon是机器epsilon,也就是说,1.0和下一个值之间的差异可以由浮点类型的T表示。但这并不一定意味着定义T(1) - std::numeric_limits<T>::epsilon会更好。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-03-07 07:44:30

您可以使用函数,不管它的名称如何,它可以通过使用适当的to参数来检索下一个可表示的值,该值在给定的起始点之前是算术的。(通常是-Infinity0+Infinity)。

无论您的nextafter实现使用什么浮点格式,通过C++的定义,这是可以移植的。(二进制对十进制,或尾数的宽度,也就是意义,或其他任何东西。)

示例:检索double类型的最近值小于1(在Windows上,使用Visual 2019年中的clang编译器),答案与1 - ε计算结果不同(如注释中所讨论的,IEEE754数字不正确;在任何2的幂以下,可表示数字是其上面的两倍):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
#include <iomanip>
#include <cmath>
#include <limits>

int main()
{
    double naft = std::nextafter(1.0, 0.0);
    std::cout << std::fixed << std::setprecision(20);
    std::cout << naft << '\n';
    double neps = 1.0 - std::numeric_limits<double>::epsilon();
    std::cout << neps << '\n';
    return 0;
}

输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
0.99999999999999988898
0.99999999999999977796

使用不同的输出格式,这可以打印为0x1.fffffffffffffp-10x1.ffffffffffffep-1 (1 - ε)。

注意,当使用类似技术来确定大于1的最近值时,nextafter(1.0, 10000.)调用提供与1 + ε计算(1.00000000000000022204)相同的值,这与ε定义中的预期值相同。

性能

C++23要求std::nextafter必须是constexpr,但目前只有一些编译器支持这一点。GCC确实通过它做了恒定的传播,但是clang不能(哥德波特).如果您希望这与0x1.fffffffffffffp-1;这样的文字常量一样快(在启用优化的情况下),对于double是IEEE754 binary64的系统,那么在某些编译器上,您将不得不等待C++23支持的这一部分。(很可能一旦编译器能够做到这一点,比如GCC,即使不实际使用-std=c++23,他们也会进行优化。)

全局作用域的const double DoubleBelowOne = std::nextafter(1.0, 0.);在最坏的情况下将在启动时运行该函数一次,从而击败了使用它的常量传播,但如果与其他运行时变量一起使用,则执行与FP文字常量大致相同的操作。

票数 26
EN

Stack Overflow用户

发布于 2022-03-07 08:37:04

这可以在不调用函数的情况下通过使用C标准中指定的浮点表示的特性来计算。由于epsilon提供了略高于1的可表示数之间的距离,而radix提供了用来表示数字的基,所以在1以下的可表示数之间的距离是epsilon除以该基:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
#include <limits>


int main(void)
{
    typedef float Float;

    std::cout << std::hexfloat <<
        1 - std::numeric_limits<Float>::epsilon() / std::numeric_limits<Float>::radix
        << '\n';
}
票数 9
EN

Stack Overflow用户

发布于 2022-03-07 14:56:26

0.9999940395355224609375是小于1的最大32位浮点数。下面的代码演示如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Mac_3.2.57$cat float2uintTest4.c 
#include <stdio.h>
int main(void){
    union{
        float f;
        unsigned int i;
    } u;
    //u.f=0.9999;
    //printf("as hex: %x\n", u.i); // 0x3f7fffff
    u.i=0x3f800000; // 1.0
    printf("as float: %200.200f\n", u.f);
    u.i=0x3f7fffff; // 1.0-e
          //00111111 01111111 11111111 11111111
          //seeeeeee emmmmmmm mmmmmmmm mmmmmmmm
    printf("as float: %200.200f\n", u.f);

    return(0);
}
Mac_3.2.57$cc float2uintTest4.c 
Mac_3.2.57$./a.out 
as float: 1.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
as float: 0.99999994039535522460937500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71383519

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文