2016-01-29 2 views
3

J'ai code simple:NetBSD longue double problème

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

Sur mon Ubuntu x64 imprime comme 3.362100e-4932 prévu. Sur mon NetBSD, il imprime 1.681050e-4932

Pourquoi ça arrive et comment puis-je le réparer? J'essaye clang et gcc avec le même résultat.

Mon système (VM VirtualBox 5.0 à l'intérieur):

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 

Pour votre information

/usr/include/x86/float.h définit comme LDBL_MIN comme 3.3621031431120935063E-4932L Et cette valeur est supérieure résultat printf.

+0

Il serait intéressant de voir le résultat de 'rd = 3.3622e-4932L,' Quelque chose juste un peu plus grand. – chux

+0

Impression de la valeur correcte 3.362200e-4932 – sibnick

Répondre

3

/usr/include/x86/float.h définit comme LDBL_MIN comme 3.3621031431120935063E-4932L Et cette valeur est supérieure résultat printf.

LDBL_MIN est le minimum positif normalisée valeur de type long double. Le type peut représenter des nombres plus petits, ils sont juste inférieurs à la normale.

Je ne peux que spéculer sur la nature du problème sur NetBSD, mais il y a deux possibilités principales:

  1. Le compilateur traduit votre constante d'initialisation en un nombre inférieur à la normale qui est assez loin (dans un sens relatif) à partir de la valeur demandée. Le numéro est traduit correctement (mais le résultat est encore inférieur à la normale), et printf() de NetBSD est bogué pour les nombres subnormaux, ou au moins pour celui-ci.

Le fait que le numéro imprimé est la moitié de ce que vous attendez suggère un problème avec l'exposant (binaire) dans la représentation long double. Étant donné les détails du format IEEE pour les nombres subnormaux, il est facile d'imaginer comment une implémentation printf() qui n'anticipe pas des nombres inférieurs à la normale pourrait mal interpréter le champ exposant (binaire) pour représenter un exposant un de moins que ce qui est réellement représenté, et donc imprimer une valeur qui est la moitié de celle attendue. Ce serait ma conjecture quant à ce qui se passe.

Vous pouvez probablement faire la distinction entre la mauvaise valeur et les mauvais cas d'affichage en imprimant, par exemple, rd * 4. Cela devrait être dans la gamme des nombres normaux de toute façon, donc on supposerait qu'un printf() bug spécifique aux nombres subnormaux n'affecterait pas l'impression.

Comme pour procéder, vous avez plusieurs choix. Les plus probables qui me viennent à l'esprit sont:

  1. Évitez les nombres inférieurs à la normale. Cela peut ne pas être pratique, mais au moins vous pouvez utiliser LDBL_MIN comme votre initialiseur au lieu d'une constante qui correspond plus étroitement à un subnormal.

  2. Ignore le problème.Si vous pouvez confirmer qu'il s'agit d'un problème d'affichage, par opposition à un problème de valeur erronée, il se peut que vous n'ayez pas besoin de faire quoi que ce soit pour servir adéquatement votre objectif plus large.

  3. Fixer la bibliothèque C de NetBSD. En supposant que le problème est dans printf(), le correctif ne serait probablement pas très grand, et la bibliothèque est open source, comme le reste du système.

  4. Déposer un rapport de bogue et attendre que quelqu'un d'autre le corrige. Si vous avez besoin d'une solution en temps opportun, cela peut ne pas convenir, mais si vous avez le temps d'attendre, cela nécessite un minimum d'effort de votre part.