Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.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++ 符合标准的比较浮动和积分的方法?_C++_Floating Point_Integer_Comparison_Language Lawyer - Fatal编程技术网

C++ 符合标准的比较浮动和积分的方法?

C++ 符合标准的比较浮动和积分的方法?,c++,floating-point,integer,comparison,language-lawyer,C++,Floating Point,Integer,Comparison,Language Lawyer,假设我有两个对象I和f,分别属于I和f类型。我知道std::is_integral::value是真的,std::is_floating_point::value是真的 是否有一种完全符合标准的方法来确定i的值是否小于f的值?请注意“完全符合标准”,对于这个问题,我只对由C++标准提供的保证支持的答案感兴趣。 琐碎的实现i

假设我有两个对象
I
f
,分别属于
I
f
类型。我知道
std::is_integral::value
是真的,
std::is_floating_point::value
是真的

是否有一种完全符合标准的方法来确定
i
的值是否小于
f
的值?请注意“完全符合标准”,对于这个问题,我只对由C++标准提供的保证支持的答案感兴趣。
琐碎的实现
i
不起作用,因为
f
的值可能不适合
i
内部。琐碎的实现
F(i)
也不起作用,因为
F
的精度可能不足以表示
i
,导致
i
四舍五入到等于
F
的值(如果使用IEEE754浮点,
16777219<16777220.F
失败)


但真正的困境来了:如果你想用
std::numeric\u limits::max
来缓解这些问题,你就回到比较浮点和整数的原始问题上来!这是因为
std::numeric_limits::max的类型与原始类型相同。

我会这样做:

我假设f是有限的,无穷和NaN的情况将在别处处理

  • 比较f和f(i),如果不相等,就完成了,f和i是<或>

  • 如果相等,则比较I(f)和I

  • 唯一的假设是:

    • 如果有一个浮点值正好等于i,那么F(i)给出该值

    • 如果有一个整数的值与f完全相同,则I(f)给出该值

    • 函数F和I的单调性

    编辑

    更明确地说,上述技巧用于编写比较函数,而不仅仅是测试相等性

    floatType F(intType i);
    intType I(floatType f);
    int cmpfi(floatType f,intType i)
    {
      assert(isfinite(f));
      if(f < F(i)) return -1;
      if(f == F(i))
      {
        if( I(f) < i ) return -1;
        return I(f) > i;
      }
      return 1;
    }
    
    floatType F(intType i);
    INTI型(f型);
    int cmpfi(浮点型f,int型i)
    {
    断言(isfinite(f));
    如果(fI;
    }
    返回1;
    }
    
    到您将此草案转换为C++代码,可以处理几种不同的FLUTYTYPE /ITENT/<
  • 如果
    f
    超出
    I
    的范围,您可以通过其符号来判断结果

  • 如果
    f
    I
    的范围内,但太大而没有小数部分,则将其作为整数进行比较

  • 否则,可以安全地将
    i
    转换为
    F
    ,因为舍入不会改变比较结果:
    F
    已经小于将舍入的
    i
    的任何值

  • 模板
    如果std::is integral\u v和&std::is floating\u point\u v,则启用,
    bool>小于(I,F){
    //提前返回不同符号的操作数。
    如果(i<0!=f<0)返回i<0;
    bool rev=i>=0;
    如果(修订版){
    f=-f;//使两个操作数都为非正。
    i=-i;//(此处的负性可避免整数溢出。)
    }
    如果(f如果(f*STD::NoimiCiLime::EpsiLon),“对于这个问题,我只对由C++标准保证的答案感兴趣”。这个问题是不合理的,愚蠢的。这类似于要求一种实现冒泡排序的方法,并且要求答案由C++标准支持。C++标准对冒泡排序没有任何说明。<代码> 代码>是“标准兼容”。找出< <代码> > <代码>小于<代码> f>代码> @ CalthHth.-阿尔夫我不同意。问题的全部要点是找到一种在C++实现上定义良好的方法。你可以为冒泡排序做这个,但是我不确定你是否可以进行比较,因此我的问题。@巴里,但它在我的Quy中失败了。stion-这显然是不对的。@orlp:不确定您是否理解您的要求。例如,您是否知道该标准支持十进制浮点表示法?您想涵盖它吗?您是否知道该标准(很可能是一场灾难)不需要对称的整数范围吗?你想要这个覆盖吗?你知道这个标准甚至不定义乘法吗?你想要这个吗?简而言之,“在任何现存的C++实现中定义的方法之间有很长的距离”,并正式保证。我正在寻找一个排序测试,而不是相等性。@orlp,我没有详细说明答案,但这些提示是为了编写一种cmp函数。好的,在步骤1中,您在发现
    f!=I
    后说“您完成了”。这显然不能解决问题:)@orlp,好的,更多的细节来帮助你推断我的想法我不接受,因为我发现了-这非常接近,但在
    std::numeric_limits::max()
    …呃,这段代码只适用于有符号整数。你可以通过去掉所有符号业务来为无符号整数添加重载。
    template< typename I, typename F >
    std::enable_if_t< std::is_integral_v< I > && std::is_floating_point_v< F >,
    bool > less( I i, F f ) {
        // Return early for operands of different signs.
        if ( i < 0 != f < 0 ) return i < 0;
    
        bool rev = i >= 0;
        if ( rev ) {
            f = - f; // Make both operands non-positive.
            i = - i; // (Negativity avoids integer overflow here.)
        }
    
        if ( f < /* (F) */ std::numeric_limits<I>::min() ) {
            // |i| < |f| because f is outside the range of I.
            return rev;
        }
        if ( f * std::numeric_limits<F>::epsilon() <= -1 ) {
            // f must be an integer (in I) because of limited precision in F.
            I fi = f;
            return rev? fi < i : i < fi;
        }
        // |f| has better than integer precision.
        // If (F) |i| loses precision, it will still be greater than |f|.
        return rev? f < i : i < f;
    }