[V3.x - v4] Truc bizarre avec un float ... [Résolu]

Archive.
Niffo
Messages : 108
Inscription : dim. 29/août/2004 15:51

[V3.x - v4] Truc bizarre avec un float ... [Résolu]

Message par Niffo »

Ce code :

Code : Tout sélectionner

a.f = 4294967295
Debug a
... retourne "-1" en PB3.94 et "4294967295" en PB4 : normal ?
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Dans la 3.94 un float est codé sur 4 octets alors que dans la V4, alors que maintenant je pense qu'elle est codée sur 8 octets.

Un nombre flottant ne peut pas dépasser la valeur d'un type long pour la 3.94 ou d'un quad pour la V4.

D'ailleurs si tu fais 4294967295.0 le compilateur t'indique que ton chiffre est trop grand!

:)
Niffo
Messages : 108
Inscription : dim. 29/août/2004 15:51

Message par Niffo »

Si le float est sur 8 octets, quelle est la différence avec le double alors ?
Normalement un float c'est sur 4 octets, sinon on risque de rencontrer des pb avec les APIs ;)
Avatar de l’utilisateur
Flype
Messages : 2431
Inscription : jeu. 29/janv./2004 0:26
Localisation : Nantes

Message par Flype »

l'entier ou le flottant sont sur 32bits, le double est sur 64bits.
Image
LeCyb
Messages : 273
Inscription : dim. 26/déc./2004 20:49

Message par LeCyb »

La preuve par l'exemple (nombres signés):

Code : Tout sélectionner

q.q = 9223372036854775807 ; 64 bits
l.l = 2147483647          ; 32 bits
w.w = 32767               ; 16 bits
b.b = 127                 ; 8 bits
f.f = 10000000 + 1 / 3    ; flottant sur 32 bits
d.d = 10000000 + 1 / 3    ; flottant sur 64 bits

Debug q
Debug l
Debug w
Debug b
Debug f
Debug d
Vive le thread-safe !
Niffo
Messages : 108
Inscription : dim. 29/août/2004 15:51

Message par Niffo »

Ah bon, c'est résolu ?

On ne sait toujours pas si c'est normal que mon exemple affiche "-1" en PB3.94 et "4294967295" en PB4.

(ce qui m'a d'ailleurs provoqué un bug super dur à tracker dans une de mes applis ...)
LeCyb
Messages : 273
Inscription : dim. 26/déc./2004 20:49

Message par LeCyb »

Les nombres à virgule flottante c'est un sujet assez délicat car le nombre est stocké grâce à un système d'exposants et donc comme l'indique la doc au plus le nombre est grand (avant la virgule) au moins la précision (après la virgule) est grande.

Pour visualiser le nombre flottant il faut donc le calculer et avec PB 3.94 le plus grand type était d'une taille de 32 bits (un long) le nombre ne dépassait pas +2147483647 (nombres signés):

Code : Tout sélectionner

;PB 3.94
f.f = 2147483647
l.l = 2147483647
Debug f
Debug l

f.f = 2147483649
l.l = 2147483649
Debug f
Debug l
Comme ce sont des nombres signés après le plus grand nombre positif on passe au plus petit nombre négatif. Si l'on continue on va passer des nombres négatifs aux positifs:

Code : Tout sélectionner

; PB 3.94
f.f = 3000000000
l.l = 3000000000
Debug f
Debug l

f.f = 4294967295
l.l = 4294967295
Debug f
Debug l

f.f = 4294967298
l.l = 4294967298
Debug f
Debug l
La version 4 de PB nous a accouché de nombres plus grands càd sur 64 bits (les quad).
Quand tu veux visualiser un float il calcule donc sur 64 bits au lieu de 32 bits ce qui fait que la limite des Long signés (+2147483647) est passé à celle des quad (+9223372036854775807 en signés).

Code : Tout sélectionner

; PB 4
f.f = 2147483649
q.q = 2147483649
l.l = 2147483649
Debug f
Debug q
Debug l
On remarque clairement que la limite du long est passée mais pas celle du float et du quad.

Le passage à des nombres négatifs se fait toujours puisque ce sont des nombres signés mais la limite est devenue celle des quad:

Code : Tout sélectionner

; PB 4
f.f = 9223372036854775807
q.q = 9223372036854775807
Debug f
Debug q

f.f = 9223372036854775808
q.q = 9223372036854775808
Debug f
Debug q
Donc c'est normal qu'avec PB3.94 il te donne -1 et pas avec PB4.

Dans les différents exemples on peut aussi clairement voir que la précision diminue au plus le nombre est grand.

Un dernier point à éclaircir, c'est que le "stockage" du nombre flottant reste sur 32bits même si son "affichage" se calcule sur 64bits:

Code : Tout sélectionner

; PB 4
b.b
w.w
l.l
q.q

f.f
d.d

Debug SizeOf(b) * 8
Debug SizeOf(w) * 8

Debug SizeOf(l) * 8
Debug SizeOf(f) * 8

Debug SizeOf(q) * 8
Debug SizeOf(d) * 8
SizeOf() donne la taille en octets donc on multiplie par 8 pour avoir le nombre de bits.
Vive le thread-safe !
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

y'a ca aussi pour compenser le nombre de décimales en PB
en plus le compilo traduit l'expression tout seul comme un grand donc c'est comme si on faisait a = valeur.

Code : Tout sélectionner

a.f = (4294967 * 1000) + 295
Debug a
là encore on a du mal à retomber sur la valeur souhaitée, c'est du au format des nombres réels (IEEE)

Dri
Fred
Site Admin
Messages : 2808
Inscription : mer. 21/janv./2004 11:03

Message par Fred »

Les explications sont bonnes, c'est bien ca.
LeCyb
Messages : 273
Inscription : dim. 26/déc./2004 20:49

Message par LeCyb »

Au début j'ai aussi un peu ramé pour comprendre les floats mais là je crois que j'ai bien assimilé le truc :D
Vive le thread-safe !
Niffo
Messages : 108
Inscription : dim. 29/août/2004 15:51

Message par Niffo »

Ok, merci pour les explications.
Je croyais que lorsque l'on stoquait dans un float (32bits), le calcul et/ou l'affichage était aussi fait sur 32 bits ...
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

Euh!!! tu confonds pas les doubles et les quads?
Et j'ai pas compris quand tu dis qu'un flottant est stocké sur 32 bits, même quand il est calculé en 64?! Les.f sont stockés en 32 bits, et les .d en 64, à moins que je devienne fou! Tu parles des calculs internes dans une évaluation, c'est ça?
Fred
Site Admin
Messages : 2808
Inscription : mer. 21/janv./2004 11:03

Message par Fred »

Ca n'empeche pas qu'un float en 32 bits a une plage de valeurs bien plus importante qu'un long en 32 bits (mais une precision entiere beaucoup moins bonne).
LeCyb
Messages : 273
Inscription : dim. 26/déc./2004 20:49

Message par LeCyb »

Je ne pense pas confondre.

Un nombre à virgule flottante est un nombre stocké différemment des nombres classiques.
Il est formé pour les floats (donc sur 32bits) d'une mantisse (23 bits), d'un exposant (8 bits) et d'un bit de signe.

Je ne vais pas détailler le truc mais prennons un exemple qui s'en rapproche: 10 ^ (exposant) 20.
Quand je dis "10 exposant 20" ce n'est pas un nombre comme on peut le voir en debug, il faut le "calculer" pour afficher 100 000 000 000 000 000 000 (y'a 20 zéros).

Les float c'est plus ou moins le même principe et donc pour l'afficher il faut "calculer". Avec PB3.94 le calcul se faisait avec des Long qui sont limités à 2^31 (31 car y'a un bit de signe) mais avec PB4 le calcul est fait avec des Quad qui peuvent monter jusque 2^63 (toujours un bit de signe).

En ce qui concerne les doubles, c'est exactement comme des floats sauf que la mantisse est de 52 bits et l'exposant est de 11 bits.
La différence c'est qu'ils ont une bien meilleure précision que les floats mais il faut savoir que ça prend plus de temps de calcul (et donc c'est plus lent).

Pour moi le meilleur exemple c'est 1/3 car il y a une infinité de chiffres après la virgule et en l'occurence c'est toujours le même.

Code : Tout sélectionner

; PB 3.94
f.f = 1 / 3
Debug f
Ici avec PB 3.94 on a 6 chiffres derrière la virgule.

Code : Tout sélectionner

; PB4
f.f = 1 / 3
d.d = 1 / 3

Debug f
Debug d
On peut voir ici que l'arrondi se fait beaucoup plus loin qu'en PB 3.94 car il est calculé grâce à des nombres plus grands (64 bits quoi).
On remarque aussi que les doubles ont une plus grande précision car ils ont une mantisse et exposant plus grands.
Vive le thread-safe !
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

Je vois vraiment pas pourquoi tu parles des quads?! Tu veux parler des dword et qword en assembleur, c'est ça?
Répondre