比较两个双打的标志

时间:2010-05-06 15:16:08

标签: visual-c++ floating-point double sign

比较double上的签名的最快方法是什么?

我知道double有一个“符号位”,但我不确定我在二进制代表中“寻找它”的方式是不是一个好主意。

除了“可移植性”问题,有人能告诉我MSVC ++中这段代码发生了什么吗?

#include <stdio.h>

int main()
{
  double z = 5.0 ;

  __int64 bitSign ;

  __int64 *ptr ;

  ptr = (__int64*)&z ;

  for( __int64 sh = 0 ; sh < 65 ; sh++ )
  {
    bitSign = 1L << sh ; // Weird.  it doesn't do 1.
    printf( "Bit# %d (%llx):  %lld\n",
      sh, bitSign, ( (*ptr) & bitSign) ) ;
  }

}

首先,为什么从第32位开始,即使我只移位了一位?

其次,我可以检查double的第64位来检查它在MSVC ++上的签名吗?

4 个答案:

答案 0 :(得分:2)

至少有三次比较 - 必须发生

  1. 提取
  2. 的标志
  3. 提取b的符号
  4. 比较a和b是否相等
  5. 没有办法避免这三件事。

    你可以做一个and,你可以做一个less than,并不重要 - 你 - 可能 - 找到一种很酷/聪明/棘手的方式来做另一种方式。但是你仍然需要进行这三个基本操作。也没有必要过度复杂化。如果你正在寻找一条坚持在一条线上的东西,你可以这样做:

    __int64 mask = 0x8000000000000000; // i think that's the right amount of 0's :-)
    if( (x&mask) ^ (y&mask) ) 
      puts("different");
    else
      puts("same");
    

    这里我正在提取它并对它们进行xor'ing。如果该位相同,则xor将为0(假) - 如果位不同,则xor将为1(真)。通过一个很好的评论来解释你正在做什么以及为什么,这是一个非常有效的方法。

    但是:你给出的“不要使用它”的例子并不是那么糟糕......它很容易阅读,这是你的代码中最重要的事情之一。优化有两个规则:

    1. 不要这样做。
    2. (仅限专家)不要这样做。
    3. 不要牺牲可读性来优化已经非常快速的东西,并且可能足够快。 : - )

答案 1 :(得分:0)

((((__int64*)(&z))*) & 0x8000000000000000) give you the sign

答案 2 :(得分:0)

double确实有一个符号位(最重要的位),但找到一个数字的符号比这复杂一点。你想区分+0.0和-0.0吗?或者在+ NaN和-NaN之间?

答案 3 :(得分:0)

在C ++ 11中,我们获得std::signbit,如果否定,则返回true,否则返回false

鉴于两个双打ab,我们可以将其标志与==!=进行比较:

void classify(double _lhs, double _rhs)
{
    std::cout << _lhs << " and " << _rhs;
    if (std::signbit(_lhs) == std::signbit(_rhs))
        std::cout << " have the same sign\n";
    else
        std::cout << " have different signs\n";
}

Live Demo

std::signbit支持doublefloatlong double和所有整数类型。它甚至可以处理NaN值。