Page 2 sur 3

Re: Existe t'il une fonction pour arrondir un float?

Publié : lun. 29/déc./2014 10:59
par Mesa
Comme ça aussi:

Code : Tout sélectionner

t.f=10.5896523
Procedure.D RoundFloat(Value.f,pLen)
ProcedureReturn (Round(value*Pow(10.0, plen),#PB_Round_Nearest)/Pow(10.0, plen))
EndProcedure
Debug RoundFloat(t,1) ;Retourne 10,6
Debug RoundFloat(t,2) ;Retourne 10,59
Debug RoundFloat(t,3) ;Retourne 10,59

M.

Re: Existe t'il une fonction pour arrondir un float?

Publié : lun. 29/déc./2014 16:43
par GallyHC
bonjour,

Mesa > un truc me vient a regarder ton code, dans ton exemple tu as :

Code : Tout sélectionner

Debug RoundFloat(t,1) ;Retourne 10,6
Debug RoundFloat(t,2) ;Retourne 10,59
La je suis ok, mais pour :

Code : Tout sélectionner

Debug RoundFloat(t,3) ;Retourne 10,59
je pense qu'il manque un chiffre après la virgule non? ne devrait' il pas avoir "10.589". Enfin je n'ai pas testé, c'est juste au regard de ce qu'il est indiqué dans ton exemple.

Cordialement,
GallyHC

Re: Existe t'il une fonction pour arrondir un float?

Publié : lun. 29/déc./2014 17:37
par MLD
Pour le fun j'ai passé une partie de la journée a essayer. SANS résultat. 8O

Le code d'origine donné par Microsoft est le suivant: (pour VB)

Code : Tout sélectionner

Function AsymArith(ByVal X As Double, _
            Optional ByVal Factor As Double = 1) As Double
     AsymArith = Int(X * Factor + 0.5) / Factor
   End Function
ou celui-ci pour de multiple décimales

Code : Tout sélectionner


Private Function Arrondi(ByVal Nombre, ByVal Decimales)     
      Arrondi = Int(Nombre * 10 ^ Decimales + 1 / 2) / 10 ^ Decimales     
End Function
J'ai traduit ce code en PB et nada :twisted: :twisted:
Il semble qu'il a un problème avec la division en interne PB??? :(
Si quelqu'un a des idées :idea:

Re: Existe t'il une fonction pour arrondir un float?

Publié : lun. 29/déc./2014 18:58
par kernadec
bonsoir
idem, j'ai essayé autrement aussi
dans ce code avec debug NF dans la procédure est bien défini, mais après la division
il y a un résidu qui traine d'où vient il . :?: ..mystère

[réédit] ou alors :idea: c'est probablement Debug qui nous induit en erreur..... en interne ce doit être correct :wink:

Cordialement

Code : Tout sélectionner

;t.f=10.5956523 
t.f=10.5496523
Procedure.D RoundFloat(Value.f,pLen) 
  Protected NI,NF,Div=1,N 
  NI = Int(value * Val(LSet("1", 2 + plen , "0"))) ; multiplication avec une décimale de plus pour arrondi round()
  NF = Int(Round((NI / 10), #PB_Round_Nearest))
  Debug NF
  For N = 1 To pLen
    Div = Div * 10
  Next
  ProcedureReturn (NF / Div)
EndProcedure 
Debug RoundFloat(t,1) ;Retourne 10,5 
Debug RoundFloat(t,2) ;Retourne 10,55 
Debug RoundFloat(t,3) ;Retourne 10,550 

Re: Existe t'il une fonction pour arrondir un float?

Publié : lun. 29/déc./2014 20:02
par kernadec
je pense qu'on à la confirmation avec code que debug n'est pas cohérent

[réédit] avec les commentaires du test affichage :wink:

Code : Tout sélectionner

Procedure.d RoundFloat(Value.f,pLen) 
  Protected NI,NF,Div=1,N 
  NI = Int(value * Val(LSet("1", 2 + plen , "0"))) ; multiplication avec une décimale de plus pour arrondi round()
  NF = Int(Round((NI / 10), #PB_Round_Nearest))
  ;Debug "entier"
 ; Debug NF
  For N = 1 To pLen
    Div = Div * 10
  Next
     ProcedureReturn NF / Div
EndProcedure
   
   
   
t.f=10.5496523  
Debug "1er nombre test"
Debug t
Debug "--debug affiche -------------------------------"
Debug RoundFloat(t,1)           ;Retourne 10,5
Debug "--Atan du resultat affiché -------------------"
Debug ATan(RoundFloat(t,1))  
Debug "--Atan du resultat attendu---------------------"
Debug ATan(10.5)
Debug "--Atan du nombre saisi que debug affiche ------"
Debug ATan(10.5)
Debug ""
Debug "###### Ici  affichage debug non conforme "
Debug "--debug affiche pour 2 décimales ----------------"
Debug RoundFloat(t,2)         ;Retourne 10.5500000000001
Debug "Ici Atan n'est pas celui du resultat affiché ????"
Debug ATan(RoundFloat(t,2)) 
Debug "mais identique à Atan du resultat attendu !------"
Debug ATan(10.55)
Debug "--Atan du nombre saisi que debug nous affiche !---"
Debug ATan(10.5500000000001)
Debug ""
Debug "-----------------------------------------------"
Debug "###### Ici  affichage debug non conforme "
Debug "--debug affiche pour 3 décimales ----------------"
Debug RoundFloat(t,3)         ;Retourne 10.5500000000001
Debug "Ici Atan n'est pas celui du resultat affiché ????"
Debug ATan(RoundFloat(t,3)) 
Debug "mais identique à Atan du resultat attendu !------"
Debug ATan(10.550)
Debug "--Atan du nombre saisi que debug nous affiche !---"
Debug ATan(10.5500000000001)
Debug ""
Debug "-----------------------------------------------"
Debug "2ème nombre test"
Debug "------ Ici l' Affichage debug est conforme"
t.f=10.5956523 
Debug t
Debug "--debug affiche -------------------------------"
Debug RoundFloat(t,1)         ;Retourne 10,6
Debug "--Atan du resultat affiché -------------------"
Debug ATan(RoundFloat(t,1))  
Debug "--Atan du resultat attendu---------------------"
Debug ATan(10.6)
Debug "--Atan du nombre saisi que debug affiche ------"
Debug ATan(10.6)
Debug ""
Debug "--debug affiche -------------------------------"
Debug RoundFloat(t,2)         ;Retourne 10,6
Debug "--Atan du resultat affiché ????----------------"
Debug ATan(RoundFloat(t,2))  
Debug "--Atan du resultat attendu---------------------"
Debug ATan(10.6)
Debug "--Atan du nombre saisi que debug affiche ------"
Debug ATan(10.6)
Debug ""
Debug "--debug affiche -------------------------------"
Debug RoundFloat(t,3)          ;Retourne 10,596 
Debug "--Atan du resultat affiché ????----------------"
Debug ATan(RoundFloat(t,3)) 
Debug "--Atan du resultat attendu---------------------"
Debug ATan(10.596)
Debug "--Atan du nombre saisi que debug affiche ------"
Debug ATan(10.596)

Re: Existe t'il une fonction pour arrondir un float?

Publié : mar. 30/déc./2014 10:13
par MLD
@kernadec
Oui c'est possible que ce soit débug ? Fred pourrait nous dire.
Quand j'aurai un peu de temps, je vais regarder autrement.
cordialement

Re: Existe t'il une fonction pour arrondir un float?

Publié : mar. 30/déc./2014 11:11
par Fred
2 choses:

1) toutes les valeurs ne sont pas representable exactement dans le format flottant. En fait tres peu le sont, les autres sont approchées. 10.57 n'est pas stockable dans le format float.

2) Utiliser les doubles pour plus de precision (c'est pareil, peu de valeurs sont representable de maniere exactes, mais leur nombre augmente beaucoup surtout avec peu de chiffre apres la virgule)

Code : Tout sélectionner

a.f = 10.57
Debug a

b.d = 10.57
Debug b
J'imagine que VB utilise les doubles par defaut, d'où la difference.

Re: Existe t'il une fonction pour arrondir un float?

Publié : mar. 30/déc./2014 15:00
par MLD
@ Fred

Merci pour ta réponse. Bonne fin d'année pour toi et ta famille.
Ceci me rend perplexe 8O

Petite démo

Code : Tout sélectionner

a.f = 105.99 / 10
Debug a

b.d = 105.99 /10
Debug b

;

Enumeration
  #Ma_fen
  #btCalcul
  #text1
  #text2
EndEnumeration


OpenWindow(#Ma_fen,0,0,400,400,"Ma Fenêtre",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
 TextGadget(#text1,40,100, 300, 25,"",#PB_Text_Border)
 TextGadget(#text2,40,200, 300, 25,"",#PB_Text_Border)
 ButtonGadget(#btCalcul, 300,350,80,30,"Calcul")

;  Boucle générale
Repeat

     EventID = WaitWindowEvent() 
      If EventID = #PB_Event_Gadget 
      Select EventGadget() 
        Case #btCalcul 
          Select EventType()
           Case #PB_EventType_LeftClick
            a.f = 105.99 / 10
            SetGadgetText(#text1,StrF(a.f))
            b.d = 105.99 /10
            SetGadgetText(#text2,StrD(b.d))
           EndSelect 
       EndSelect 
   EndIf 
Until EventID = #PB_Event_CloseWindow 
End

Il ne reste plus qu'a construire le round_décimales.

Re: Existe t'il une fonction pour arrondir un float?

Publié : mar. 30/déc./2014 15:29
par djes
Il faut savoir aussi que l'erreur est plus ou moins grande selon la décimale. A ta place, je convertirais tout en entier pour tes calculs d'arrondis, c'est beaucoup plus rapide. Il ne faut pas non plus perdre de vue qu'un arrondi représente une énorme perte de précision !

Comme le dit fred, pour avoir plus de précision avec les nombres à virgule, il faut utiliser le type "double" (il est là pour ça, il ne faut pas s'en priver !). Avec les doubles, l'erreur est extrêmement faible, il faut des millions (?) d'itérations pour commencer à se rendre compte de quelque chose, c'est bien plus précis qu'un horrible arrondi !

Code : Tout sélectionner

OrgFloatNumber.f=10.5689474123

NumberInteger.i = OrgFloatNumber * 100
Debug NumberInteger
NewFloatNumber.d = (NumberInteger / 100)
Debug NewFloatNumber


Re: Existe t'il une fonction pour arrondir un float?

Publié : mar. 30/déc./2014 15:36
par MLD
@ microdevweb

voila ta solution, mais comme le dit Fred et djes passe tous tes calculs en type double

Code : Tout sélectionner

;

Enumeration
  #Ma_fen
  #btCalcul
  #text1
EndEnumeration

Procedure.D Round_decimales(nombre.d,dec.d)
 ProcedureReturn Int(nombre * Pow(10,dec) + 0.5) / Pow(10,dec)    
EndProcedure

OpenWindow(#Ma_fen,0,0,400,400,"Ma Fenêtre",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
TextGadget(#text1,40,100, 300, 25,"",#PB_Text_Border)
ButtonGadget(#btCalcul, 300,350,80,30,"Calcul")
;  Boucle générale
Repeat

     EventID = WaitWindowEvent() 
      If EventID = #PB_Event_Gadget 
      Select EventGadget() 
      
        Case #btCalcul 
          Select EventType()
           Case #PB_EventType_LeftClick
            
            SetGadgetText(#text1,StrD(Round_decimales(10.5689474123,2)))
            
           EndSelect 
       EndSelect 
   EndIf 
Until EventID = #PB_Event_CloseWindow 
End

Sur ce Bonne fin d'année a tous.

Re: Existe t'il une fonction pour arrondir un float?

Publié : mar. 30/déc./2014 15:41
par Micoute
Moi je pense que le plus simple c'est de ne travailler qu'avec des entiers : la partie entière, dans un integer et la partie décimale, dans un autre integer.

Re: Existe t'il une fonction pour arrondir un float?

Publié : mar. 30/déc./2014 15:48
par microdevweb
Merci à tous pour vos réponses.

Re: Existe t'il une fonction pour arrondir un float?

Publié : mar. 30/déc./2014 15:58
par MLD
ou comme ceci

Code : Tout sélectionner

a.f = 10.5789474123 ;*******************
Enumeration
  #Ma_fen
  #btCalcul
  #text1
EndEnumeration

Procedure.D Round_decimales(nombre.d,dec.d)
 ProcedureReturn Int(nombre * Pow(10,dec) + 0.5) / Pow(10,dec)    
EndProcedure

OpenWindow(#Ma_fen,0,0,400,400,"Ma Fenêtre",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
TextGadget(#text1,40,100, 300, 25,"",#PB_Text_Border)
ButtonGadget(#btCalcul, 300,350,80,30,"Calcul")
;  Boucle générale
Repeat

     EventID = WaitWindowEvent() 
      If EventID = #PB_Event_Gadget 
      Select EventGadget() 
      
        Case #btCalcul 
          Select EventType()
           Case #PB_EventType_LeftClick
            
            ;SetGadgetText(#text1,StrD(Round_decimales(10.5689474123,2)))
            SetGadgetText(#text1,StrD(Round_decimales(a,2)))
           EndSelect 
       EndSelect 
   EndIf 
Until EventID = #PB_Event_CloseWindow 
End


Re: Existe t'il une fonction pour arrondir un float?

Publié : mar. 30/déc./2014 18:43
par Micoute
Pour ne pas rester en reste:

Code : Tout sélectionner

Define.d a = 10.5789474123 ;*******************
Enumeration
  #Ma_fen
  #btCalcul
  #str0
  #str1
  #txt0
  #text1
EndEnumeration

Procedure.D Round_decimal(nombre.d, dec.d)
  ProcedureReturn Int(nombre * Pow(10, dec) + 0.5) / Pow(10, dec)
EndProcedure

OpenWindow(#Ma_fen, 0, 0, 400, 300, "Round_Decimal", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
StringGadget(#str0, 40, 50, 300, 25, StrD(a))
TextGadget(#txt0, 40, 100, 110, 25, "Nombre de décimales:")
StringGadget(#str1, 150, 95, 20, 25, "2")
TextGadget(#text1, 40, 150, 300, 25, "", #PB_Text_Border)
ButtonGadget(#btCalcul, 150, 200, 80, 30, "Calculer")
;  Boucle générale
Repeat
  
  EventID = WaitWindowEvent()
  If EventID = #PB_Event_Gadget
    Select EventGadget()
        
      Case #btCalcul
        Select EventType()
          Case #PB_EventType_LeftClick
            a = ValD(GetGadgetText(#str0))
            SetGadgetText(#text1, StrD(Round_decimal(a, Val(GetGadgetText(#str1)))))
        EndSelect
    EndSelect
  EndIf
Until EventID = #PB_Event_CloseWindow
End

Re: Existe t'il une fonction pour arrondir un float?

Publié : mar. 30/déc./2014 19:17
par Mesa
C'est tout le problème des nombres flottant.

Dans la doc de purebasic, dans la page "Variables, Types et Opérateurs", on peut lire :
Informations concernant les nombres flottants

Un nombre flottant est stocké de telle manière que la 'virgule flotte' autour de la partie réelle. De la sorte, il est possible d'avoir des nombres dont la valeur peut être aussi bien grande que petite. Toutefois vous ne pouvez pas stocker de grands nombres avec une précision aussi élevée que des petits nombres.

Une autre limitation concernant les nombres flottants est qu'ils restent concrètement représentés sous une forme binaire. Ainsi, ils ne peuvent être restitués qu'à partir de multiples et de divisions en base 2. Celà est important pour comprendre que la représentation décimale lors de l'affichage ou du calcul n'est pas tout à fait identique à ce que l'on peut attendre dans une représentation humaine. Représenter 0.5 ou 0.125 est simple car ce sont des divisions parfaites de 2, cela est plus complexe pour des nombres comme 0.11 ou 0.10999999. L'affichage approché de la valeur est toujours correct à un nombre limité de décimales, mais ne soyez pas surpris si au-delà le nombre affiché s'écarte de la valeur que vous attendez!

Ces remarques s'appliquent aux nombres flottants traités par ordinateur d'une manière générale et non spécifiquement à Purebasic.

Comme leur nom l'indique, les 'doubles' sont des flottants 'double-precision' (64-bit) comparativement aux flottants 'simple-precision' que sont les floats (32-bit). Donc, pour avoir plus de précision dans la manipulation des nombres à virgule, il est préférable d'utiliser les 'doubles'.

Pour plus d'information sur le format 'IEEE 754', consulter l'article Wikipedia.


Voir ici : http://fr.wikipedia.org/wiki/Virgule_flottante
surtout à la rubrique "Précision arbitraire" et "Précautions d'emploi".

A savoir: les nombres et les calculs avec des float sont toujours justes même si leur affichage est bizarroïde.
On ne peut pas avoir un affichage propre à moins de le programmer soi même ou d'utiliser une fonction toute prête comme la fonction printf de cette dll pour purebasic par exemple (que je n'ai pas testé): http://www.purebasic.fr/english/viewtop ... 12&t=61315

M.