Astuces et codes utiles sur les Mathématiques

Partagez votre expérience de PureBasic avec les autres utilisateurs.
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Astuces et codes utiles sur les Mathématiques

Message par nico »

Vous pouvez poster ici tous les codes et infos concernant l'utilisation des mathématiques sous Pure Basic.

:)
bombseb
Messages : 445
Inscription : jeu. 25/août/2005 22:59
Localisation : 974
Contact :

Message par bombseb »

aller je commence par "Soche caches toi"

SOH CAH TOA


Sinus = Coté opposé / Hypotenuse
Cosinus = Coté adjacent / Hypotenuse
Tagente = Coté opposé / Coté adjacent
bombseb
Messages : 445
Inscription : jeu. 25/août/2005 22:59
Localisation : 974
Contact :

Message par bombseb »

un autre truc tout con :

Chiffre négatif = ennemis
chiffre positif = amis

les amis de mes amis sont mes amis : un chiffre positif * un chiffre positif = un chiffre positif

marche avec toutes les combinaisons...
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

Les fonctions de maths sont relativelent gourmandes en performances... Quelques situations où on peut éviter de s'en servir ou s'en servir sans en abuser... (j'édite au fur et à mesure)

Toutes les fonctions sont compatibles avec EnableExplicit


comparer une valeur à une racine carrée

Code : Tout sélectionner

a.f = 2.0
b.f = 4.0

If a = Sqr(b)
  Debug "ca fonctionne"
EndIf

If (a * a) = b
  Debug "ca fonctionne aussi"
EndIf
ca peut être utile dans les comparaisons de distances. si a et b deux distances, et a2 et b2 les carrés (puissance 2) respectifs alors :
a < b <=> a2 < b2
a = b <=> a2 = b2 etc...
il n'est pas utile de calculer les distances complètement pour les comparaisons... la racine encore une fois est obsolete.


complément trigo : convertir des angles

Code : Tout sélectionner

#RadToDeg = 180.0 / #PI
#RadToGrd = 200.0 / #PI
#DegToRad = #PI / 180.0
#DegToGrd = 200 / 180.0
#GrdToRad = #PI / 200.0
#GrdToDeg = 180 / 200.0

Macro RadToDeg(Rad)
  ((Rad) * #RadToDeg)
EndMacro

Macro RadToGrd(Rad)
  ((Rad) * #RadToGrd)
EndMacro

Macro DegToRad(Deg)
  ((Deg) * #DegToRad)
EndMacro

Macro DegToGrd(Deg)
  ((Deg) * #DegToGrd)
EndMacro

Macro GrdToRad(Grd)
  ((Grd) * #GrdToRad)
EndMacro

Macro GrdToDeg(Grd)
  ((Grd) * #GrdToDeg)
EndMacro
Vive les macros et la constante #PI :D


complément trigo : Sécante, Cosécante, Cotangente

Code : Tout sélectionner

Macro Sec(Angle)
  (1.0 / Cos(Angle))
EndMacro

Macro Csc(Angle)
  (1.0 / Sin(Angle))
EndMacro

Macro Cot(Angle)
  (1.0 / Tan(Angle))
EndMacro
ne me demandez pas d'exemple d'utilisation :P


complément trigo : Arc Tangent

Code : Tout sélectionner

Procedure.d ATan2(dy.d, dx.d)
  !FLD qword [p.v_dy]
  !FLD qword [p.v_dx]
  !FPATAN
  ProcedureReturn
EndProcedure

Procedure.d ATanFull(dy.d, dx.d)
  Protected Angle.d
 
  If dx = 0.0
    If dy > 0 : Angle = #PI / 2.0
    Else : Angle = 3.0 * #PI / 2.0
    EndIf
  ElseIf dy = 0.0
    If dx > 0 : Angle = 0.0
    Else : Angle = 2.0 * #PI
    EndIf
  Else
    !FLD    qword [p.v_dy]
    !FLD    qword [p.v_dx]
    !FPATAN
    !FSTP   qword [p.v_Angle]
  EndIf
 
  If Angle < 0.0
    Angle + (2.0 * #PI)
  EndIf
 
  ProcedureReturn Angle
EndProcedure

OpenWindow(0, 0, 0, 400, 400, "ATanFull", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)

Repeat
  If StartDrawing( WindowOutput(0) )
   
   
    Box(0, 0, 400, 400, #White)
   
    DrawingMode(#PB_2DDrawing_Outlined|#PB_2DDrawing_Transparent)
   
    Circle(200, 200, 150, #Black)
    Line(20, 200, 360, 0)
    Line(200, 20, 0, 360)
   
    DrawText(352, 200, "0")
    DrawText(184, 350, "90")
    DrawText( 22, 184, "180")
    DrawText(202,  20, "270")
    DrawText(352, 184, "360")
   
    x = WindowMouseX(0)
    y = WindowMouseY(0)
   
    If x>=0 And y>=0 And x<400 And y<400
     
      dx = x - 200
      dy = y - 200
     
      angle.f = RadToDeg( ATan(dy / dx) )
      DrawText(0,  0, "ATan : " + StrF(angle))
     
      angle.f = RadToDeg( ATan2(dy, dx) )
      DrawText(0, 16, "ATan2 : " + StrF(angle))
     
      angle.f = RadToDeg( ATanFull(dy, dx) )
      DrawText(0, 32, "ATanFull : " + StrF(angle))
     
      LineXY(200, 200, x, y, #Red)
    EndIf
   
    StopDrawing()
  EndIf
Until WaitWindowEvent() = #PB_Event_CloseWindow
avec en prime un exemple pour illustrer... plus précis que l'arc tangent simple (-Pi/2 < angle < Pi/2 je crois)


Plus Grand Diviseur Commun et Plus Petit Multiple Commun

Code : Tout sélectionner

Procedure GCD(a.l, b.l)
  Protected c.l
  
  If a And b
    While b   
      c = a % b
      a = b
      b = c
    Wend
    
    If a < 0
      a = -a
    EndIf
  Else
    a = 0
  EndIf
  
  ProcedureReturn a
EndProcedure

Procedure LCM(a.l, b.l)
  Protected c.l
  
  If a And b
    c = a * b / GCD(a, b)
    If c < 0
      c = -c
    EndIf
  EndIf
  
  ProcedureReturn c
EndProcedure

Debug GCD( 12,  15)
Debug GCD( 12, -15)
Debug GCD(-12,  15)
Debug GCD(-12, -15)

Debug "---"

Debug LCM( 12,  15)
Debug LCM( 12, -15)
Debug LCM(-12,  15)
Debug LCM(-12, -15)
Si si ca peut servir :P


connaître le signe d'un nombre

Code : Tout sélectionner

Macro Sgn(Number)
  ((Number > 0 Or #False) - (Number < 0 Or #False))
EndMacro

Debug Sgn(-5)
Debug Sgn(-0)
Debug Sgn( 5)

Debug Sgn(-5.0)
Debug Sgn(-0.0)
Debug Sgn( 5.0)
Nan franchement ca non-plus c'est pas inutile :lol:


probabilités : Factorielle, Combinaisons, Arrangements

Code : Tout sélectionner

Procedure.d Factorial(n.l)
  Protected r.d
  
  If n >= 0
    r = 1
    
    While n > 1
      r * n
    Wend
  EndIf
  
  ProcedureReturn r
EndProcedure

Procedure.d Combinations(n.l, p.l)
  Protected r.d
  
  If n >= 0 And p >= 0
    
    If n >= p
      r = 1.0
      
      If p > n / 2
        p = n - p
      EndIf
      
      While p > 0
        r * n / p
        n - 1
        p - 1
      Wend
      
      If r - Round(r, 0) > 0.5
        r + 1
      EndIf
    EndIf
    
  EndIf
  
  ProcedureReturn Round(r, 0)
EndProcedure

Procedure.d Permutations(n.l, p.l)
  Protected r.d
  
  If n >= 0 And p >= 0
    
    If n >= p
      r = 1.0
      
      p = n - p
      
      While n > p
        r * n
        n - 1
      Wend
    EndIf
    
  EndIf
  
  ProcedureReturn r
EndProcedure
Je retourne des nombres réels au lieu d'entiers (ca peut parasiter à 10^-9 environ) parce que ça grimpe très vite... pour vous convaincre voici un exemple avec une version récursive des combinaisons. Elle met chez moi plus de 10 secondes à fournir le même résultat, très gros comparé aux valeurs n et p.

Code : Tout sélectionner

Procedure.l C(n.l, p.l)
  Protected r
  
  If n < 0 Or p < 0
    r = 0
  ElseIf p = 0 Or n = p
    r = 1
  Else
    r = C(n-1, p-1) + C(n-1, p)
  EndIf
  
  ProcedureReturn r
EndProcedure

Debug C(25, 15)
J'ai ajouté l'arrondi pour les combinaisons ^^, et voila un petit exemple
(je chercherais un moyen plus propre d'arrondir...)

Code : Tout sélectionner

n = 50

For p = 0 To n
  Debug "C(" + Str(n) + ", " + Str(p) + ") = " + StrD(Combinations(n, p), 20)
Next p
Dri
Dernière modification par Dr. Dri le dim. 11/févr./2007 16:38, modifié 18 fois.
bombseb
Messages : 445
Inscription : jeu. 25/août/2005 22:59
Localisation : 974
Contact :

Message par bombseb »

ah oué pas con
bombseb
Messages : 445
Inscription : jeu. 25/août/2005 22:59
Localisation : 974
Contact :

Message par bombseb »

un truc aussi pour éviter de faire des multiplications ou divisions (gourmand aussi en perf)

pour multiplier un nombre par 2
plutot que de faire
resultat = n * 2

il faut mieux faire :
resultat = shl(n, 1)

un shl déplace tout les bits du nombre de pas indiqué vers la gauche, ce qui équivaut à une multiplication et c'est beaucoup plus rapide

shl(n, 2) = multplication par 4
shl(n, 3) = multiplication par 8
shl(n, 4) = multiplication par 16
shl(n,x) = multiplication par 2^x

même principe pour les divisions avec shr

astuce : si vous voulez multiplier par 5, faites un shl(n,2) et ajoutez n

(ps : je n'ai pas encore regardé dans PB si les fonction shl et shr existent...si elle n'existent pas on peut toujour le faire en assembleur dans le code PB)
fweil
Messages : 505
Inscription : dim. 16/mai/2004 17:50
Localisation : Bayonne (64)
Contact :

Message par fweil »

Le mieux serait de regarder avant de poster.

Le compilateur effectue une addition pour les multiplications par deux et un décalage pour les multiplications par des puissnaces de deux autres.

Ce qui est parfaitement optimisé.
Mon avatar reproduit l'image de 4x1.8m présentée au 'Salon international du meuble de Paris' en janvier 2004, dans l'exposition 'Shades' réunisant 22 créateurs autour de Matt Sindall. L'original est un stratifié en 150 dpi.
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

a + a est plus rapide que a << 1 ? c'est vraiment de l'optimisation ?

Code : Tout sélectionner

#i = 1000000000

b.l = 1

a = ElapsedMilliseconds()
For i = 0 To #i
  b + b
Next i
a = ElapsedMilliseconds() - a
MessageRequester("*2 version +", Str(a), 16)

a = ElapsedMilliseconds()
For i = 0 To #i
  b << 1
Next i
a = ElapsedMilliseconds() - a
MessageRequester("*2 version <<", Str(a), 16)
sans debugger bien sûr
j'obtiens 15000+ et 14500+

Dri :!:
fweil
Messages : 505
Inscription : dim. 16/mai/2004 17:50
Localisation : Bayonne (64)
Contact :

Message par fweil »

Ce n'est pas une différence significative en fait.

Selon le fait de lancer le même test à différents moments et de placer les deux séquences dans un sens ou dans l'autre on obtient des résultats instables.

De fait l'addition d'un registre sur lui-même prend exactement le même temps si j'en crois les specs Intel, soit un cycle. Mais le rendu dans le cadre d'un prog qui est lancé par l'OS n'est pas forcément aussi précis.

Dans tous les cas le shift d'un bit n'est pas plus rapide.
Mon avatar reproduit l'image de 4x1.8m présentée au 'Salon international du meuble de Paris' en janvier 2004, dans l'exposition 'Shades' réunisant 22 créateurs autour de Matt Sindall. L'original est un stratifié en 150 dpi.
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

Avoir un processeur AMD ca peut jouer ?

Dri
fweil
Messages : 505
Inscription : dim. 16/mai/2004 17:50
Localisation : Bayonne (64)
Contact :

Message par fweil »

@Dr. Dri,

Non le principe de basculement d'un registre sur lui-même est invariant chez tous les fondeurs.

Et il n'y a aucun gain non plus à tenter de jouer sur deux registres, en raison du temps de copie d'un registre sur un second, qui prend au minimum le même temps que la ré-injection du contenu d'un registre sur lui-même.

On en restera toujours à un cycle minimum quelque soit le chemin que l'on prenne.
Mon avatar reproduit l'image de 4x1.8m présentée au 'Salon international du meuble de Paris' en janvier 2004, dans l'exposition 'Shades' réunisant 22 créateurs autour de Matt Sindall. L'original est un stratifié en 150 dpi.
bombseb
Messages : 445
Inscription : jeu. 25/août/2005 22:59
Localisation : 974
Contact :

Message par bombseb »

Le compilateur effectue une addition pour les multiplications par deux et un décalage pour les multiplications par des puissnaces de deux autres.
ah bon ?? ah ben je ne savais pas...
Heis Spiter
Messages : 1092
Inscription : mer. 28/janv./2004 16:22
Localisation : 76
Contact :

Message par Heis Spiter »

Résolution d'un trinôme... Ça peut toujours servir.

Code : Tout sélectionner

Procedure.s trinome(a, b , c)
  d = b*b - 4*a*c
  If d < 0
    ProcedureReturn "d < 0"
  ElseIf d = 0
    ProcedureReturn Str(-b/2*a)
  Else
    ProcedureReturn Str((-b-Sqr(d))/2*a)+"|"+Str((-b+Sqr(d))/2*a)
  EndIf
EndProcedure
Dernière modification par Heis Spiter le ven. 09/sept./2005 17:32, modifié 1 fois.
Heis Spiter, webmaster du site http://www.heisspiter.net
Développeur principal et administrateur du projet Bird Chat
Parti courir au bonheur du dév. public et GPL :D
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

mon astuce sur les racines carrées ca vaut aussi pour les carrés
remplace le Pow(b, 2) par b*b

Dri :0:
Heis Spiter
Messages : 1092
Inscription : mer. 28/janv./2004 16:22
Localisation : 76
Contact :

Message par Heis Spiter »

Bien vu ;), b*b est plus rapide ! C'est pas :0:, mais :10:
Heis Spiter, webmaster du site http://www.heisspiter.net
Développeur principal et administrateur du projet Bird Chat
Parti courir au bonheur du dév. public et GPL :D
Répondre