2016-01-29 2 views
3

У меня есть простой код:NetBSD длинный двойной неприятности

#include <stdio.h> 

int main() 
{ 
     //char d[10] = {0x13, 0x43, 0x9b, 0x64, 0x28, 0xf8, 0xff, 0x7f, 0x00, 0x00}; 
     //long double rd = *(long double*)&d; 
     long double rd = 3.3621e-4932L; 
     printf("%Le\n", rd); 
     return 0; 
} 

На моей Ubuntu x64 он печатает, как и ожидалось 3.362100e-4932. На моем NetBSD он печатает 1.681050e-4932

Почему это происходит и как я могу его исправить? Я пробую clang и gcc с тем же результатом.

Моя система (ВМ внутри VirtualBox 5.0):

uname -a 
NetBSD netbsd.home 7.0 NetBSD 7.0 (GENERIC.201509250726Z) amd64 

gcc --version 
gcc (nb2 20150115) 4.8.4 

clang --version 
clang version 3.6.2 (tags/RELEASE_362/final) 
Target: x86_64--netbsd 
Thread model: posix 

FYI

/usr/include/x86/float.h определяет как LDBL_MIN как 3.3621031431120935063E-4932L И это значение больше, чем результат PRINTF.

+0

Было бы интересно посмотреть, как результат 'й = 3.3622e-4932L;' что-то чуть больше. – chux

+0

Он печатает правильное значение 3.362200e-4932 – sibnick

ответ

3

/usr/include/x86/float.h определяет как LDBL_MIN как 3.3621031431120935063E-4932L И это значение больше, чем результат PRINTF.

LDBL_MIN является минимальным положительным нормализуется значение типа long double. Тип может представлять меньшие числа, они просто субнормальные.

Я могу только догадываться о природе проблемы на NetBSD, но есть два основные варианта:

  1. Компилятор переводит вашу константу инициализации в субнормальное число, которое довольно далеко (в относительном смысле) из запрошенного значения.

  2. Число переведено точно (но результат по-прежнему является субнормальным), а NetBSD printf() является ошибкой для субнормальных чисел или, по крайней мере, для этого.

Тот факт, что число печатных составляет половину от того, что вы ожидаете, предполагает проблему с (бинарной) показатель степени в long double представлении. Учитывая детали формата IEEE для субнормальных чисел, легко представить себе, как реализация printf(), которая не ожидает субнормальных чисел, может неверно истолковать (двоичное) поле экспоненты, чтобы представить экспоненту меньше, чем на самом деле, и, следовательно, печатать значение, равное половине ожидаемого. Это было бы моим предположением о том, что происходит.

Возможно, вы можете различать неправильное значение и неправильные витрины, а также печатать, скажем, rd * 4. Это должно быть в диапазоне нормальных чисел в любом случае, поэтому можно предположить, что ошибка printf(), характерная для субнормальных чисел, не повлияет на ее печать.

Как действовать, у вас есть несколько вариантов. Наиболее вероятными для меня являются:

  1. Избегайте субнормальных чисел. Это может быть непрактично, но по крайней мере вы можете использовать LDBL_MIN в качестве вашего инициализатора вместо константы, которая наиболее точно соответствует субнормальному long double.

  2. Игнорировать проблему.Если вы можете подтвердить, что это проблема с отображением, в отличие от проблемы с неправильной стоимостью, возможно, вам не нужно ничего делать, чтобы адекватно служить вашей более широкой цели.

  3. Исправить библиотеку C библиотеки NetBSD. Предположим, что проблема находится в printf(), исправление, вероятно, не будет очень большим, а библиотека является открытым исходным кодом, как и остальная часть системы.

  4. Сообщите об ошибке и дождитесь, пока кто-нибудь еще ее исправит. Если вам нужно своевременное исправление, это может оказаться неприемлемым, но если у вас есть время подождать, это потребует немалых усилий с вашей стороны.