Сегодня я отслеживал, почему моя программа выдает некоторые неожиданные ошибки несоответствия контрольной суммы в некотором написанном мной коде, который сериализует и десериализует значения с плавающей запятой IEEE-754 в формате, который включает 32-битное значение контрольной суммы (которое вычисляется путем выполнения алгоритма типа CRC над байтами массива с плавающей запятой
Немного поцарапав голову, я понял, что проблема в том, что 0.0f и -0.0f имеют разные битовые шаблоны (0x00000000 и 0x00000080 (с прямым порядком байтов), соответственно), но они считаются эквивалентными Оператор равенства C ++. Итак, ошибки несоответствия контрольной суммы произошли из-за того, что мой алгоритм вычисления контрольной суммы уловил разницу между этими двумя битовыми шаблонами, в то время как некоторые другие части моей кодовой базы (которые используют проверку равенства с плавающей запятой, а не рассматривают значения побайтно. byte) не проводил такого различия.
Хорошо, честно - в любом случае я должен был знать лучше, чем проводить проверку равенства с плавающей запятой.
Но это заставило меня задуматься, есть ли другие плавающие запятой IEEE-754 значения, которые считаются равными (согласно оператору C ==), но имеют разные битовые шаблоны? Или, говоря другими словами, как именно оператор == определяет, равны ли два значения с плавающей запятой? Я новичок, хотя он делал что-то вроде memcmp () в их битовых шаблонах, но очевидно, что это более тонко, чем это.
Вот пример кода того, что я имею в виду, на случай, если я не понял выше.
#include <stdio.h>
static void PrintFloatBytes(const char * title, float f)
{
printf("Byte-representation of [%s] is: ", title);
const unsigned char * p = (const unsigned char *) &f;
for (int i=0; i<sizeof(f); i++) printf("%02x ", p[i]);
printf("\n");
}
int main(int argc, char ** argv)
{
const float pzero = -0.0f;
const float nzero = +0.0f;
PrintFloatBytes("pzero", pzero);
PrintFloatBytes("nzero", nzero);
printf("Is pzero equal to nzero? %s\n", (pzero==nzero)?"Yes":"No");
return 0;
}