Page 1 sur 4

Astuces et codes utiles sur les Mathématiques

Publié : lun. 05/sept./2005 17:15
par nico
Vous pouvez poster ici tous les codes et infos concernant l'utilisation des mathématiques sous Pure Basic.

:)

Publié : lun. 05/sept./2005 19:23
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

Publié : lun. 05/sept./2005 19:27
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...

Publié : mar. 06/sept./2005 6:58
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

Publié : mar. 06/sept./2005 11:12
par bombseb
ah oué pas con

Publié : mar. 06/sept./2005 11:20
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)

Publié : mar. 06/sept./2005 11:30
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é.

Publié : mar. 06/sept./2005 14:18
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 :!:

Publié : mar. 06/sept./2005 15:56
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.

Publié : mar. 06/sept./2005 18:14
par Dr. Dri
Avoir un processeur AMD ca peut jouer ?

Dri

Publié : mar. 06/sept./2005 19:49
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.

Publié : mer. 07/sept./2005 7:56
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...

Publié : ven. 09/sept./2005 17:24
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

Publié : ven. 09/sept./2005 17:27
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:

Publié : ven. 09/sept./2005 17:31
par Heis Spiter
Bien vu ;), b*b est plus rapide ! C'est pas :0:, mais :10: