Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 表示小于1的最大浮点量_C++_C_Math - Fatal编程技术网

C++ 表示小于1的最大浮点量

C++ 表示小于1的最大浮点量,c++,c,math,C++,C,Math,我在做一些四舍五入的计算,偶然发现了一个问题。对于给定的浮点类型,如何表示小于1的最大数量 也就是说,我如何写入/表示值x,使得x=1对于任何y>0 在分数中,这将是x=(q-1)/q,其中q是类型的精度。例如,如果您以1/999增量计数,则x=998/999 对于给定类型(浮点、双精度、长双精度),如何在代码中表示值x 我还想知道y的所有值是否都存在这样的值。也就是说,随着y的指数变小,可能关系不再成立。因此,在y上有一定范围限制的答案也是可以接受的。(我想要的x的值仍然存在,该关系可能无法

我在做一些四舍五入的计算,偶然发现了一个问题。对于给定的浮点类型,如何表示小于1的最大数量

也就是说,我如何写入/表示值
x
,使得
x<1,x+y>=1
对于任何
y>0

在分数中,这将是
x=(q-1)/q
,其中
q
是类型的精度。例如,如果您以
1/999
增量计数,则
x=998/999

对于给定类型(浮点、双精度、长双精度),如何在代码中表示值
x



我还想知道
y
的所有值是否都存在这样的值。也就是说,随着
y的
指数变小,可能关系不再成立。因此,在
y
上有一定范围限制的答案也是可以接受的。(我想要的
x
的值仍然存在,该关系可能无法正确地表达它。)

有一种方法可以获取添加到1会产生大于1的最小可表达量的最低数量。这是
std::numeric\u limits::epsilon()
。如果你证明这个数量等于你搜索的数量,那就是你想要的:

模板静态\u Tp std::numeric\u limits<\u Tp>::epsilon()throw()[内联,静态] 机器ε:1与可表示的大于1的最小值之间的差值


C99定义了
nextafter()
函数。像这样使用它

#include <math.h>
double under_one = nextafter(1, 0);
#包括
双下一个=下一个(1,0);

尽管其他人认为小于
1
的较大值是
1-FLT\u EPSILON
,但在浮点运算中,对于任何
y>0
,它都不能满足条件
x<1,x+y>=1
,除非使用四舍五入


原因是1和它之前的距离(即
FLT_EPSILON
~1.2E-7)远大于最小可表示正数
FLT_MIN
,即~1.2E-38。因此,存在一类数字(
FLT\u MIN…FLT\u EPSILON/2
当四舍五入到最近值时,这是大多数系统的默认值),其
(1-FLT\u EPSILON)+y==(1-FLT\u EPSILON)<1

IEEE 754浮点表示法具有这样一个特性:对于正数而非
NaN
的数字,其顺序与视为整数的位模式的顺序相同


因此,您可以将浮点数1.0的位模式重新解释为整数,减小该整数,然后再次将其解释为浮点数,以使浮点数刚好低于1。

根据IEEE 754标准,单精度(32位)1.0的表示形式为0x3F800000。我们可以将其以二进制形式写成0 01111111(1)00000000000000000000000,这意味着:

sign = 0
biased exponent = 01111111 = 0x7F, so exponent = -23 (decimal)
mantissa = 0x800000 (the (1) in parentheses is the implied msb)
因此该值为0x800000*2^-23,即1.0。下一个最低的单精度数字是

0 01111110 (1)11111111111111111111111
或者0x3F7FFFFF,或者0xFFFFFF*2^-24,大约为0.999999 4。

函数
nextafter()
运行良好

#包括
//从1.0到0.0查找下一个double
前两倍=后一倍(1.0,0.0);

然而,要以编译时的值这样做,正如作者以一种高度可移植的方式所评论的:

#include <float.h>
double before_1 = 1.0 - DBL_EPSILON/FLT_RADIX;
#包括
前双精度=1.0-DBL\uε/FLT\u基数;
DBL_EPSILON
是1.0和下一个更大的
double
之间的绝对差值


FLT_RADIX
是浮点系统的基数。通常是2。使用了16和10之类的值。

您是否在寻找某种公式?常数?找到它的算法?最好是一个常数,但也可以接受一个函数netlib@Chris
1
是用二进制精确表示的,所以像我写的那样使用它将给您提供最大可能的“小于1”的双值是的,这似乎正是我想要的。有没有办法把这个值表示成常数?也就是说,如果我想用它作为默认参数?如果我们假设epsilon朝向0.0比朝向2.0精细两倍,我们可以使用FLT_epsilon常量,除以2。@Chris:1不是1的实现是无法超越所有可用性的。C可能允许这样的中断,但除非您假设自己是理智的,否则编写任何浮点代码都毫无意义。就我个人而言,我总是假设IEEE 754语义和表示。是否保证
1-epsilon+epsilon==1
?答案可能是“否”。我尝试使用nextafter()函数,试图得到从1.0到0.0再到2.0的ε-结果是不同的。Epsilon Toward 2.0正好是Toward 0.0的两倍-可能是因为后者使用非规范化数字表示,该数字的精度多了1位。对于二进制浮点,1-Epsilon将太大。例如,使用3位二进制数字的FP格式:1.00之后的下一个数字是1.01,因此epsilon是0.01,而1.00之前的数字是0.111。@edA:C对浮点结果没有任何保证。IEEE 754当然保证了这一点,因为所有涉及的值都是精确的。这也是很好的了解。它解决了我对这个数字是否可能的担忧。这难道不意味着从1.0到0.0的ε是FLT_ε/2吗?我不确定这是真的,但似乎是真的。我可能在细节上错了。范围可以是FLT_MIN…FLT_EPSILON/4,而不是/2,因为它是实际EPSILON的一半,但它是存在的。好吧,IEEE-754表示法意味着隐藏的MSB始终等于1(除非它是非规范数)。因此,低于1.0的最高数量将表示为所有一(1)尾数和(-1)指数。该数字的MSB将是一个隐含的(1),因此尾数实际上会多接收一位。这就是为什么朝向0.0的ε比朝向2.0的ε细2倍。
#include <float.h>
double before_1 = 1.0 - DBL_EPSILON/FLT_RADIX;