[ZX SPECTRUM] Virgule flottante... je nage! (codes C++)

Cette catégorie traite de développements récents pour nos vieilles machines, applications, jeux ou démos... Amis programmeurs, c'est ici que vous pourrez enfin devenir célèbres!

Modérateurs : Papy.G, fneck, Carl

Xavier_AL

Re: [ZX SPECTRUM] Virgule flottante... je nage!

Message par Xavier_AL »

... Archimède ?
Oui, j'ai l'impression... car les variables Basic en entier, sont "pures" et les variables résultantes de calculs sont encodées en exponentielles!
Donc, il y a un décodage en fonction du bit fort sur le 1er octet.
Il faut que je te sorte des valeurs variables autres qu'entières (GOTO xxx).
Xavier_AL

Re: [ZX SPECTRUM] Virgule flottante... je nage!

Message par Xavier_AL »

:oops:
Je confirme:
Capture.JPG
Capture.JPG (63.61 Kio) Consulté 3846 fois

Les tableaux DIM x(), ne sont pas traduits en entiers, mais en virgules flottantes.
Et c'est bien cette valeur qui me pose problème.

Ici, deux fichiers... (capture écran)
1 basic
10 DIM a(1)
20 LET a=1/1
30 SAVE"datas"DATA a()

où 1=00;00;01;00;00

1 Fichier data:
a(1)=1
81;00;00;00;00
Xavier_AL

Re: [ZX SPECTRUM] Virgule flottante... je nage!

Message par Xavier_AL »

Donc, j'ai tout bien vérifié...

Mais, petite question subsidiaire...
j'affiche le résultat avec :
printf("%d :\r\n",DecNumber);
:?:
ça m'affiche les DOUBLE ou les INTEGER en C++ ?
Sinon, ça peut venir de là!
:mrgreen:
Avatar de l’utilisateur
hlide
Messages : 3469
Inscription : 29 nov. 2017 10:23

Re: [ZX SPECTRUM] Virgule flottante... je nage!

Message par hlide »

Ca dépend comment est déclaré la variable DecNumber. En l'occurence, elle est déclarée ici comme double. Je suppose que tu n'utilises pas gcc ? parce qu'il aurait dû te sortir un warning si tu n'utilises pas le bon code de format : %f et non %d. Là, il te sortira en base décimal la représentation interne binaire du nombre et probablement tronquée à 32-bit.
Xavier_AL

Re: [ZX SPECTRUM] Virgule flottante... je nage!

Message par Xavier_AL »

Salut à tous,

Voilà, ça fonctionne.
J'ai pris le code de Samuel (mais en le divisant par 2):

Code : Tout sélectionner


//*******************************************************************
// Spectrum/ZX810 Floating point decoder From _SAM_
//*******************************************************************

double resultat = decode(LineData);	
		   fprintf(out,"%f\r\n",resultat);
		   
double decode(unsigned char fp[5]) { 
	double mantisse;
		
	if(fp[0]==0) return 0;	
	mantisse = (((fp[4]/256.0 + fp[3])/256.0 + fp[2])/256.0 + fp[1])/128.0;	
	if(mantisse < 1) mantisse += 1;  // nombre positif
	else mantisse = -mantisse; // nombre negatif
	
	return mantisse*pow(2, fp[0]-128)/2;
}

Le problème venait bien du %d à l'affichage, au lieu du %f. (affichage de la valeur tronquée)
Je suis sur le "TDM-GCC 4.9.2" sous Dev-C++ , et aucun message lors de la compilation.

Donc, Merci à tous pour votre aide, vos conseils et votre expertise!
hlide pour tes conseils (et ton code), Sam pour tes connaissance en routines de décodage...
Et tous les curieux qui ont suivi ce fil.

J'upload le binaire w32/64 sur ce fil, des que le programme sera cohérent.

(Merci Fabien pour le déplacement du message! toujours discret, et toujours efficace...)
__sam__
Messages : 7923
Inscription : 18 sept. 2010 12:08
Localisation : Brest et parfois les Flandres

Re: [ZX SPECTRUM] Virgule flottante... je nage! (codes C++)

Message par __sam__ »

au lieu de diviser par 2 à la fin, tu peux faire fp[0]-129 au lieu de 128.
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Avatar de l’utilisateur
hlide
Messages : 3469
Inscription : 29 nov. 2017 10:23

Re: [ZX SPECTRUM] Virgule flottante... je nage! (codes C++)

Message par hlide »

Eventuellement, tu peux modifier la routine pour extraire l'entier codé dans le cas où fp[0] == 0 :

Code : Tout sélectionner


//*******************************************************************
// Spectrum/ZX810 Floating point decoder From _SAM_
//*******************************************************************

double resultat = decode(LineData);	
		   fprintf(out,"%f\r\n",resultat);
		   
double decode(unsigned char fp[5]) { 
	double mantisse;
		
	if(fp[0]==0) return 1.*(fp[2]+fp[3]*256+fp[4]*65536);	
	mantisse = (((fp[4]/256. + fp[3])/256. + fp[2])/256. + fp[1])/128.;	
	if(mantisse < 1.) mantisse += 1.;  // nombre positif
	else mantisse = -mantisse; // nombre negatif
	
	return mantisse*pow(2, fp[0]-129);
}
__sam__
Messages : 7923
Inscription : 18 sept. 2010 12:08
Localisation : Brest et parfois les Flandres

Re: [ZX SPECTRUM] Virgule flottante... je nage! (codes C++)

Message par __sam__ »

dans le cas des entiers, comment est-ce que le signe est géré ? Est-ce le bit 7 de fp[1] qui compte comme pour les flottants? Si c'est le cas il faudrait avoir:

Code : Tout sélectionner

if(fp[0]==0) return (fp[1]&128 ? 1. : -1.)*(fp[2]+fp[3]*256+fp[4]*65536);
Xavier: tu as quoi comme valeurs fp[] pour les entiers 65535, -1, -2, et -256 par exemple.
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Avatar de l’utilisateur
hlide
Messages : 3469
Inscription : 29 nov. 2017 10:23

Re: [ZX SPECTRUM] Virgule flottante... je nage! (codes C++)

Message par hlide »

__sam__ a écrit : 17 avr. 2018 11:52 dans le cas des entiers, comment est-ce que le signe est géré ?
Exact. Soit c'est le bit 7 de fp[4] comme pour une valeur entière habituelle, soit on peut imaginer que c'est le fp[1]. D'ailleurs, est-ce qu'ils auraient pas fait un truc assez tordu pour que ce soit quelque chose de ce genre :

Code : Tout sélectionner

return 1. * int(fp[1] * 16777216 + fp[4] * 65536 + fp[3] * 256 + fp[2]);
Avatar de l’utilisateur
hlide
Messages : 3469
Inscription : 29 nov. 2017 10:23

Re: [ZX SPECTRUM] Virgule flottante... je nage! (codes C++)

Message par hlide »

Et en big-endian, ça nous donnerait :

Code : Tout sélectionner

return 1. * int(fp[1] * 16777216 + fp[2] * 65536 + fp[3] * 256 + fp[4]);
j'ai cru lire ici qu'il y aurait une différence de little/big-endian dans la représentation entre Spectrum et Amstrad ?
Xavier_AL

Re: [ZX SPECTRUM] Virgule flottante... je nage! (codes C++)

Message par Xavier_AL »

:oops:
Oui Samuel, comme tu le présageais, nous avons un problème de signe/bit7 sur f[1]

Code : Tout sélectionner

Comment : Created with EightyOneTZX

Header bloc program [BASIC]
Name...:'basic     '

Block 1:
Start line: 32768.
10 DIM a(10)
20 LET a(1)=65535
30 LET a(2)=-1
40 LET a(3)=-2
50 LET a(4)=-256
60 SAVE "datas" DATA a()

Header bloc program Num. ARRAY]
Name...:'datas     '

Block 2:
Array(10) :
-65535.000000
65535.000000
65534.000000
65280.000000
-0.000000
-0.000000
-0.000000
-0.000000
-0.000000
-0.000000
Sur ce code:

Code : Tout sélectionner

//*******************************************************************
// Spectrum/ZX81 Floating point decoder From _SAM_
//*******************************************************************
//IN: 5 Bytes : 1 EXP + 4 Mantissa (sign on the secound byte)
//OUT: DOUBLE
double decode(unsigned char fp[5]) { 
	double mantisse;
	
   if(fp[0]==0) return (fp[1]&128 ? 1. : -1.)*(fp[2]+fp[3]*256+fp[4]*65536);
	mantisse = (((fp[4]/256.0 + fp[3])/256.0 + fp[2])/256.0 + fp[1]))/128.0;	
	if(mantisse < 1) mantisse += 1;  // nombre positif
	else mantisse = -mantisse; // nombre negatif
	
	return mantisse*pow(2, fp[0]-129);
}
Il faut retirer le bit 7 avant le calcul...
__sam__
Messages : 7923
Inscription : 18 sept. 2010 12:08
Localisation : Brest et parfois les Flandres

Re: [ZX SPECTRUM] Virgule flottante... je nage! (codes C++)

Message par __sam__ »

Je ne pige pas. Le bit 7 de quel octet dans le calcul en cas d'entier ?
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Avatar de l’utilisateur
hlide
Messages : 3469
Inscription : 29 nov. 2017 10:23

Re: [ZX SPECTRUM] Virgule flottante... je nage! (codes C++)

Message par hlide »

Donne plutôt le résultat en représentation interne en hexa comme tu avais fait auparavant. Ca n'a aucun intérêt de le faire faire sur la fonction que t'a donné __sam__ (ou la mienne) car on cherche justement à voir cette représentation pour en déduire la bonne formule.

Ces résultats :
65535 -> -65535.000000
-1 -> 65535.000000
-2 -> 65534.000000
-4 -> 65280.000000

montrent juste que la formule proposée n'est pas bonne.

Cela montre que le bit 7 de fp[1] ne porte pas le signe à cause de 65535, sinon aurait pas -65535.0.
Les autres montrent que le bit de signe existe mais qu'il est ailleurs.

Voyons :
-1 -> 65535 == 00h 0???????b FFh FFh 00h
-2 -> 65534 == 00h 0???????b FEh FFh 00h
-4 -> 65280 == 00h 0???????b 00h FFh 00h

Le -4 donne un résultat encore plus bizarre. On en saura davantage avec les représentations internes (image des codes hexadécimaux).
Xavier_AL

Re: [ZX SPECTRUM] Virgule flottante... je nage! (codes C++)

Message par Xavier_AL »

Oui, pardon...
Donc les valeurs en Basic, premier fichier, sont toujours en positif.
La parie à la fin, c'est l'enregistrement du tableau a(10), avec les 10 valeurs.
Capture.JPG
Capture.JPG (95.24 Kio) Consulté 3763 fois
0x00, 0x00, 0xFF, 0xFF, 0x00, >>> pour 65535
0x00, 0xFF, 0xFF, 0xFF, 0x00, >>> pour -1
0x00, 0xFF, 0xFE, 0xFF, 0x00,>>> pour -2
0x00, 0xFF, 0x00, 0xFF, 0x00, >>> pour -256

0x00, 0x00, 0x00,0x00,0x00,>>> pour 0
0x00, 0x00, 0x00, 0x00,0x00,>>> pour 0
0x00, 0x00, 0x00, 0x00,0x00,>>> pour 0
....
Et c'est plus clair comme ça!
Enfin, non... il y a une part d'incohérence sur le f[1] du signe(bit poids fort).. à 0x0FF et non à 0x080
Il nous fait un saque en 0x7FFFFF (XOR FF) sur la valeur négative? (sauf les 0)
Xavier_AL

Re: [ZX SPECTRUM] Virgule flottante... je nage! (codes C++)

Message par Xavier_AL »

10 DIM a(100)
20 For i=1 TO 100
40 LET a(i)=-i/100
50 NEXT a
60 SAVE "datas" DATA a()

(commence en offset 70, dernier octet est à exclure '53')
Négatifs: (Ok en décodage) -0.01 à -1
Capture.JPG
Capture.JPG (166.58 Kio) Consulté 3756 fois
Positifs: (Ok en décodage) 0.01 à 1
Capture.JPG
Capture.JPG (157.03 Kio) Consulté 3754 fois
Répondre