Bonjour,
est ce qu'il existe une manière de caster un simple précision vers un double et qui en plus met à 0 les chiffres rajoutés par le cast?
Exemple:
REAL :: x =1.6
REAL(x,KIND=8) j'aimerais avoir 1.60000000
Merci d'avance
Bonjour,
est ce qu'il existe une manière de caster un simple précision vers un double et qui en plus met à 0 les chiffres rajoutés par le cast?
Exemple:
REAL :: x =1.6
REAL(x,KIND=8) j'aimerais avoir 1.60000000
Merci d'avance
La réponse sera générale car je viens de changer d'ordinateur et je n'ai encore ni mes sources, ni de compilateur...
La difficulté de ton problème est que tu vois la valeur en décimales alors qu'à l'interne, la valeur est représentée en binaire. Ainsi, 0.1 décimale est difficilement représentable en binaire. Ça vaut environ 1/16 + 1/32 + 1/256 + 1/512 + 1/4096 + 1/8192 + 1/65536 + 1/131072 + ... Dans ton exemple, tu vois 1.6, mais rien ne dit qu'à l'interne, ce n'est pas 1.599998. Veux-tu alors avoir 1.59999800000000 ? Par rapport à 1.6, est-ce plus précis que 1.5999986326484 ?
Pour obtenir ce que tu veux, tu devras probalement forcer un arrondi par rapport au résultat des fonctions precision() et/ou spacing().
Je sais pour la représentation. Mais la valeur qui est rajouté à la fin c'est bien au hasard? (ça dépend ce qu'il y avait avant dans la mémoire non?)
C'est ça que je n'aime pas. Vu que je fais une grosse somme de produit d'un Real avec un Double Precision j'ai peur que ça perturbe beaucoup mon résultat.
Je ne pense pas. Je ne connais pas vraiment ce sujet, mais je crois que le processeur ne fait « qu'ajouter des zéros », mais en binaire. En décimales, il est possible que tu vois des chiffres résultants de la conversion en décimales des fractions binaires. Dans mon exemple pour représenter 0.1, le terme 1/131072 vaut un bit en binaire, mais vaut 0.00000762939453125 en décimales. Le « bruit » que semble introduire la conversion est selon moi la conséqquance de la perte de précision initiale lors de la conversion (lecture) de décimale à binaire, perte que tu ne peux évidemment récupérer en convertissant de simple précision à double précision.
D'accord, merci pour la réponse. Je pensais vraiment que c'était aléatoire les valeurs qu'on pouvait lire quand on passait d'un float à un double.
bonjour
c'est une melasse et non plus un calcul.
il y a une mantisse et un exposant.
simple precision 32 bits:
-bit signe :1
-exposant : sur 8 bits
-mantisse sur 23 bits =>approximativ.7 chiffres decimaux,23Log(2)base10=6.923
double precision :64 bits
- bit signe :1
- exposant :sur 11 bits
- mantisse :sur 52 bits =>approximativ.16 choffres decimaux,53Log(2)base10=15.955
Dans ton cas ou tu caste vers un type dont la precision est plus grande c'est archi-clair .
Qui peut le plus peut le moins .
La mantisse du double precision etant plus grande ,il ne faut pas sortir de saint cyr pour voir que le simple precision sera contenu integralement dans la mantisse du double sans perte de precision.
Les choses seraient effectivement dramatiques si tu faisais l'inverse ,caster du double vers le simple ,parce la majorite des compilateurs font la troncature de ce qui deborde par le bas naturellement pour la mantisse et pour l'exposant.
1er exemple de double a simple:
De double à simple precision voici un exemple edifiant de perte de precision:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 ! -------------------------------------------------- ! Silverfrost FTN95 for Microsoft Visual Studio ! Free Format FTN95 Source File ! -------------------------------------------------- !Exemple des fonctions FCORE4 et DCORE8 du Silverfrost Fortran !Elles donnent la representation interne machine. PROGRAM test REAL*4 :: r4 REAL*8 :: r8 !de simple precision à double r4= 1.6 r8 = r4 PRINT*,"r4: ",r4 PRINT*,"code r4: ",FCORE4(loc(r4)) PRINT*,"r8:" ,r8 PRINT*,"core r8:" ,DCORE8(loc(r8)) pause END !resultats ! r4 : 1.60000 ! core r4: 1.60000 ! r8 : 1.60000002384 ! dcore r8: 1.60000002384
Il faut mediter sur les calculs et le choix des types au depart et pas en cours de route...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 !Exemple des fonctions FCORE4 et DCORE8 du Silverfrost Fortran !Elles donnent la representation interne machine. PROGRAM Test2 REAL*4 :: r4 REAL*8 :: r8 REAL*4 :: r44 REAL*8 :: r88 !de double à simple precision grands nombres !j'ai pris en sens inverse expres le meme nombre r8 = 1.60000002384 r4= r8 PRINT*,"r8:" ,r8 PRINT*,"core r8:" ,DCORE8(loc(r8)) PRINT*,"r4: ",r4 PRINT*,"code r4: ",FCORE4(loc(r4)) !de double à simple precision grands nombres(influence de l'exposant) ! plus grand exposant pour : !r4 : 2 puissance 127 => 10 puissance 39 !r8 :2 puissance 1023 => 10 puissance 308 !NB: si met r88 = 0.25e+40 il plante:number out if range car simple precision !ne peut avoir un exposant de plus de 39 r88 = 0.25e+39 r44 = rr8 PRINT*,"r88:" ,r88 PRINT*,"core r8:" ,DCORE8(loc(r88)) PRINT*,"r44: ",r44 PRINT*,"code r44: ",FCORE4(loc(r44)) pause END !resultats !r8: 1.60000002384 !core r8: 1.60000002384 !r4: 1.60000 !code r4: 1.60000 ! !resultats avec exposant en limite ! !r88: 2.500000072190E+38 !core r8: 2.500000072190E+38 !r44: 0.00000 !code r44: 0.00000
Bon code...
bonjour
c'est une melasse et non plus un calcul.
il y a une mantisse et un exposant.
simple precision 32 bits:
-bit signe :1
-exposant : sur 8 bits
-mantisse sur 23 bits =>approximativ.7 chiffres decimaux,23Log(2)base10=6.923
double precision :64 bits
- bit signe :1
- exposant :sur 11 bits
- mantisse :sur 52 bits =>approximativ.16 choffres decimaux,53Log(2)base10=15.955
Dans ton cas ou tu caste vers un type dont la precision est plus grande c'est archi-clair .
Qui peut le plus peut le moins .
La mantisse du double precision etant plus grande ,il ne faut pas sortir de saint cyr pour voir que le simple precision sera contenu integralement dans la mantisse du double sans perte de precision.
Les choses seraient effectivement dramatiques si tu faisais l'inverse ,caster du double vers le simple ,parce la majorite des compilateurs font la troncature de ce qui deborde par le bas naturellement pour la mantisse et pour l'exposant.
1er exemple de double a simple:
De double à simple precision voici un exemple edifiant de perte de precision:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 ! -------------------------------------------------- ! Silverfrost FTN95 for Microsoft Visual Studio ! Free Format FTN95 Source File ! -------------------------------------------------- !Exemple des fonctions FCORE4 et DCORE8 du Silverfrost Fortran !Elles donnent la representation interne machine. PROGRAM test REAL*4 :: r4 REAL*8 :: r8 !de simple precision à double r4= 1.6 r8 = r4 PRINT*,"r4: ",r4 PRINT*,"code r4: ",FCORE4(loc(r4)) PRINT*,"r8:" ,r8 PRINT*,"core r8:" ,DCORE8(loc(r8)) pause END !resultats ! r4 : 1.60000 ! core r4: 1.60000 ! r8 : 1.60000002384 ! dcore r8: 1.60000002384
Il faut mediter sur les calculs et le choix des types au depart et pas en cours de route...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 !Exemple des fonctions FCORE4 et DCORE8 du Silverfrost Fortran !Elles donnent la representation interne machine. PROGRAM Test2 REAL*4 :: r4 REAL*8 :: r8 REAL*4 :: r44 REAL*8 :: r88 !de double à simple precision grands nombres !j'ai pris en sens inverse expres le meme nombre r8 = 1.60000002384 r4= r8 PRINT*,"r8:" ,r8 PRINT*,"core r8:" ,DCORE8(loc(r8)) PRINT*,"r4: ",r4 PRINT*,"code r4: ",FCORE4(loc(r4)) !de double à simple precision grands nombres(influence de l'exposant) ! plus grand exposant pour : !r4 : 2 puissance 127 => 10 puissance 39 !r8 :2 puissance 1023 => 10 puissance 308 !NB: si met r88 = 0.25e+40 il plante:number out if range car simple precision !ne peut avoir un exposant de plus de 39 r88 = 0.25e+39 r44 = rr8 PRINT*,"r88:" ,r88 PRINT*,"core r8:" ,DCORE8(loc(r88)) PRINT*,"r44: ",r44 PRINT*,"code r44: ",FCORE4(loc(r44)) pause END !resultats !r8: 1.60000002384 !core r8: 1.60000002384 !r4: 1.60000 !code r4: 1.60000 ! !resultats avec exposant en limite ! !r88: 2.500000072190E+38 !core r88: 2.500000072190E+38 !r44: 0.00000 !code r44: 0.00000
Bon code...
Partager