Сравните знак двух двойных - PullRequest
3 голосов
/ 06 мая 2010

Какой самый быстрый способ сравнить знак на 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, хотя я сдвинут только на один бит?

Во-вторых, можно ли мне проверить 64-й бит double, чтобы проверить его знак в MSVC ++?

Ответы [ 4 ]

2 голосов
/ 06 мая 2010

Как минимум, есть три сравнения, которые должны произойти

  1. извлечение знака
  2. извлечение знака б
  3. сравните a и b на равенство

Невозможно избежать этих трех вещей.

Вы можете сделать 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 будет 0 (ложь) - если биты разные, xor будет 1 (истина). С хорошим комментарием, объясняющим, что вы делаете и почему, это совершенно правильный способ сделать это.

ОДНАКО: пример, который вы привели как «не используйте это», на самом деле не так уж и плох ... Легко читать, что является одной из самых важных вещей, которые вы можете иметь в своем коде. Существует два правила оптимизации:

  1. Не делай этого.
  2. (только для экспертов) Пока не делайте этого.

Не жертвуйте читабельностью ради оптимизации чего-то, что уже чертовски быстро и, вероятно, будет достаточно быстрым. : -)

0 голосов
/ 13 августа 2017

В C ++ 11 нам дали std::signbit, который возвращает true, если отрицательно , и false в противном случае.

С учетом двух двойных чисел a и b мы можем сравнить их знаки с == или !=:

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";
}

Демо-версия


std::signbit поддерживает double, float, long double и все интегральные типы. Он даже может обрабатывать NaN значений.

0 голосов
/ 07 мая 2010

double имеет знаковый бит (самый значимый бит), но найти знак числа немного сложнее, чем это. Хотите различить +0.0 и -0.0? Или между + NaN и -NaN?

0 голосов
/ 06 мая 2010
((((__int64*)(&z))*) & 0x8000000000000000) give you the sign
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...