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 :
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.
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
Il semble qu'il a un problème avec la division en interne PB???
Si quelqu'un a des idées

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

c'est probablement Debug qui nous induit en erreur..... en interne ce doit être correct
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
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)
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
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.