C++ 如果两个分数的分母都是2的幂,我能比较两个分数吗

C++ 如果两个分数的分母都是2的幂,我能比较两个分数吗,c++,floating-point,C++,Floating Point,我知道比较两个实数是不“可能”的,但分母幂为2的实数是真的吗 这个国王的平等总是真的吗 if( 3/4. == 6/8. ) {} 此类表达式的计算结果应始终为true,但需要注意以下几点: 分子不超过2^52;否则它们将失去精度 分母不超过双精度提供的范围 您必须在使用基数2浮点(基本上所有现代机器)的平台上工作 一般来说,浮点相等比较是否有效并不取决于值,而是取决于它们是如何获得的 e、 g 尽管值不精确,但可能工作良好,同时: double v = 0; for( int i =

我知道比较两个实数是不“可能”的,但分母幂为2的实数是真的吗

这个国王的平等总是真的吗

if( 3/4. == 6/8. ) {}

此类表达式的计算结果应始终为
true
,但需要注意以下几点:

  • 分子不超过2^52;否则它们将失去精度
  • 分母不超过双精度提供的范围
  • 您必须在使用基数2浮点(基本上所有现代机器)的平台上工作

一般来说,浮点相等比较是否有效并不取决于值,而是取决于它们是如何获得的

e、 g

尽管值不精确,但可能工作良好,同时:

 double v = 0;
 for( int i = 0; i < 5; ++i ) v += 0.1;
 if (v == 0.5) { ... }
double v=0;
对于(inti=0;i<5;++i)v++=0.1;
如果(v==0.5){…}

即使不等式的两边都可以表示为一个简单的有理数,其中分母是2的幂。

我不能引用任何东西说它是有保证的,但从逻辑上讲它应该是有效的,因为所有IEE754浮点数都表示为M*2^E,其中M和E都是整数(可能是负数)

因此,
3/4.0
6/8.0
都完全等于3*2^-2,并且完全可以用IEE754格式表示

此外,鉴于:

% cat test.cc
double three_quarters = 3 / 4.0;
double six_eighths = 6 / 8.0;
我们得到:

% c++ -S test.cc
% cat test.s
.globl _three_quarters
        .data
        .align 3
_three_quarters:
        .long   0
        .long   1072168960
.globl _six_eighths
        .align 3
_six_eighths:
        .long   0
        .long   1072168960

这表明这两个表达式都被(编译器)还原为相同的常量值。

< P>不要求C++实现使用IEEE 754浮点(或类似)。.但是如果你的成功了,这应该很好。

@Saphrosit:因为我想得到确认和建议/comment@Saphrosit:浮点错误非常复杂,依靠测试随机值是得出错误结论的好方法。你到底想做什么?下面有很多好答案,如果你有IEE754浮点运算,然后精确地表示二的小的幂和(基本上是任何你可以写的数字,就像一个简短的二进制展开一样)。但是你真的需要比较数字吗?如果数字比较很重要,你可以通过“最后一位的单位”(ULP)检查比较,这是比较IEE754浮点值的一个好方法。我可以使用boost::math::float_distance(a,b)或nextafter来检查两个浮点值是双精度的还是相邻然后相等的?它看起来像是
boost::math::float_distance
确实实现了ULP计数,所以您可以使用它来查看两个浮点值是否“几乎相等”(如果它们之间的差异小于,比如说,3 ULP或类似的东西),但现在我不知道你想要什么。我不理解你最后的评论语言,我也不明白这与代表2幂的特殊浮点数有什么关系。为什么分母不能变得太大,你能完成吗please@Guillaume07:嗯,在这种情况下,这么大(或者事实上,这么小)它们超出了双精度的范围。很可能不会成为你们关心的问题。另外要考虑的是,分子是否会超过2 ^ 52(否则它们会丢失精度)。2,53,实际上,因为前导1没有显式存储。(或
static\u assert
)在依赖此项之前,
std:numeric\u limits::radix==2
。第二个示例恰好导致相等。@奥利:在哪个系统上?标准不允许。例如,不允许。我同意不能保证它们相等。但在IEEE-754中(双精度或单精度)求和结果确实是0.5。C++不要求IEEE74浮标和加倍,但是;
% c++ -S test.cc
% cat test.s
.globl _three_quarters
        .data
        .align 3
_three_quarters:
        .long   0
        .long   1072168960
.globl _six_eighths
        .align 3
_six_eighths:
        .long   0
        .long   1072168960