Обнаружение отрицательного 0, сохраненного как двойное в С++
Я делаю некоторые математические вычисления (пытаюсь преобразовать код Matlab в С++, используя VS2010), и мне нужно уметь определить, получится ли в какой-то момент отрицательное 0.
В соответствии со стандартом IEEE -0/+ 0 отличаются только знаковым битом (остальные 0).
Я использовал следующий фрагмент кода (post), чтобы интерпретировать мой двойной как unsigned char
double f = -5;
unsigned char *c = reinterpret_cast<unsigned char *>(&f);
for(int i=(sizeof(double)-1); i>=0; i--){
printf("%02X", c[i]);
}
Попытка с 5/-5 получить ожидаемый результат:
C014000000000000 (-5)
4014000000000000 (5)
Но когда я пытаюсь сделать это с 0/-0, я получаю только нули в обоих случаях. VS2010 утверждает, что они совместимы с IEEE (msdn), поэтому я не уверен, какую часть из них я не получаю.
Если 0/-0 действительно хранится в памяти точно таким же образом, я не могу сказать им обособленно, если мне нужно, чтобы я прекратил тратить свое время:) Правильно?
Ответы
Ответ 1
Если вы пишете
double d = -0;
произойдет следующее:
Сначала будет оценен -0, который имеет тип int, потому что 0 имеет тип int. Результат будет равен 0. Тогда 0 будет преобразован в double и присвоен таким образом, что он равен +0,0, а не -0,0
double d = -0.0; // is your solution.
Ответ 2
В дополнение к хорошему ответу Армена, вы должны использовать signbit, чтобы обнаружить это. Это защитит вас от проблем со стороны:
#include <iostream>
#include <cmath>
int main()
{
std::cout << std::signbit(0.0) << '\n';
std::cout << std::signbit(-0.0) << '\n';
}
0
1
Ответ 3
Такая же функция переписывается в более короткую форму:
static inline unsigned bool signbit(double& d)
{
return ( ((unsigned char*)&d)[sizeof(double)-1] & 0x80) != 0;
}
int EstimateDoubleBufferSize( double& d )
{
int len = 0;
if( signbit(d) ) //if ( d < 0 )
{
d = -d;
len++;
}
d += 0.0000005;
int m = (int) log10(d);
if( m < 0 )
m = 1; // 0.xxxx - include 0
else
m++; // Include first character
len += m + 1 /*dot*/ + 6 /* precision after . */;
return len;
}
Также мне нужно было выяснить, какой компилятор microsoft С++ sprintf size включен и для этой функции.