2017-07-25 3 views
-2

Tout d'abord, le nombre à virgule flottante demi-précision IEEE754 utilise 16 bits. Il utilise un signe de 1 bit, un exposant de 5 bits et une mantisse de 10 bits. la valeur réelle peut être calculée comme étant signe * 2^(exposant-15) * (1 + mantisa/1024).
J'essaie d'exécuter un programme de détection d'image en utilisant la demi-précision. Le programme d'origine utilise une seule précision (= float). J'utilise la classe demi-précision dans http://half.sourceforge.net/. En utilisant la classe half, je peux au moins exécuter le même programme (en utilisant half au lieu de float et compiler avec g ++ au lieu de gcc, et après beaucoup de castings de type ..)
J'ai trouvé un problème où la multiplication semble être mauvaise .La multiplication de demi-précision semble produire un mauvais résultat

Voici l'exemple de code pour voir le problème (Pour imprimer le nombre demi-précision, je devrais le lancer pour flotter pour voir la valeur et le lancer automatique n'a pas lieu dans les opérations de moitié et entier donc je mets quelques castings ..):

#include <stdio.h> 
#include "half.h" 
using half_float::half; 
typedef half Dtype; 

main() 
{ 
#if 0 // method 0 : this makes sx 600, which is wrong. 

int c = 325; 
Dtype w_scale = (Dtype)1.847656; 
Dtype sx = Dtype(c*w_scale); 
printf("sx = %f\n", (float)sx); // <== shows 600.000 which is wrong. 

#else // method 1, which also produces wrong result.. 

int c = 325; 
Dtype w_scale = (Dtype)1.847656; 
Dtype sx = (Dtype)((Dtype)c*w_scale); 
printf("sx = %f\n", (float)sx); 
printf("w_scale specified as 1.847656 was 0x%x\n", *(unsigned short *)&w_scale); 

#endif 
} 

le résultat ressemble à ceci:

w_scale = 0x3f63 
sx = 600 
sx = 0x60b0 

Mais le sx doit être 325 * 1,847656 = 600,4882. Qu'est-ce qui peut être mauvais?

AJOUTER: Lorsque j'ai posté cette question pour la première fois, je ne m'attendais pas à ce que la valeur soit exactement 600.4882 mais quelque part proche. J'ai trouvé plus tard la demi-précision, avec sa limitation d'exprimer seulement 3 ~ 4 chiffres effectifs, la valeur la plus proche de la multication vient d'être juste 600.00. Bien que tout le monde sache que le point flottant a ce genre de limitations, certaines personnes commettront une erreur comme moi en oubliant que la demi-précision ne peut avoir que 3 ~ 4 chiffres effectifs. Je pense donc que cette question mérite d'être examinée par les futurs demandeurs. (Dans stackoverflow, je pense que certaines personnes prennent juste toutes les questions comme la même vieille question quand il s'agit en fait d'un cas légèrement différent et ça ne blesse pas d'avoir quelques questions similaires.)

+1

* "compiler avec g ++ au lieu de gcc" * parce que vous utilisez une bibliothèque en-tête C++ uniquement. De plus, votre définition 'main' est fausse, elle est supposée être' int main''. Et il produit une mauvaise sortie parce que vous lancez 'float' - essayez d'utiliser' std :: cout' comme décrit dans les exemples sur le site de la bibliothèque, ou utilisez 'half_cast' (également fourni par la bibliothèque) – UnholySheep

+0

respect, vous devriez apprendre la programmation d'abord, avant de faire des recherches sur la détection d'image ou des nombres à virgule flottante. Vous ne pouvez pas produire des résultats fiables sans compétences de programmation de base et connaissances de base dans vos outils. –

+0

@NickyC J'ai oublié int main() return 0; quand j'ai posté la question. J'ai parfois travaillé avec des codes C++ mais ces temps-ci avec C. et je ne pense pas que je devrais "apprendre" la programmation à nouveau. C'est juste que je change de langue au travail, C, C++, Python, Verilog, VHDL, etc. Et parce que la source originale est en C, j'essaye de maintenir le code le plus possible. C'est un énorme programme C avec beaucoup de fichiers. –

Répondre

-1

J'ai compris pourquoi. La demi-précision a une précision effective d'environ log10 (2^10) ~ 3 ou 4 chiffres. Je voulais que le sx soit imprimé comme 600.488 ou quelque chose de proche, mais cela ne peut pas être représenté en utilisant la demi-précision. Cette partie est venue pendant le prétraitement d'image qui peut être faite sans précision de 16 bits (notre matériel de tentative), ainsi je peux juste utiliser l'opération de flotteur pour cette étape.
AJOUTER: cette anomalie est survenue pendant le calcul de la dimension de l'image, et nous n'avons aucune raison d'utiliser un flottant de 16 bits pour ce cas. Les données d'image simples (données de pixel ou de carte d'entités) doivent utiliser le flottant 16 bits. Après avoir écrit ceci, c'est une règle générale.