Ştiri:

Vă rugăm să citiţi Regulamentul de utilizare a forumului Scientia în secţiunea intitulată "Regulamentul de utilizare a forumului. CITEŞTE-L!".

Main Menu

limbaje de programare: CAZ CONCRET. 1.

Creat de florin_try, Aprilie 13, 2010, 05:17:20 AM

« precedentul - următorul »

0 Membri şi 1 Vizitator vizualizează acest subiect.

florin_try

 S-a discutat anterior despre limbaje de programare asa in principiu dar ma intrebam oare nu ar fi mai ilustrativ sa luam un mic exemplu concret
de exercitiu (ceva f.f. simplu) si sa il rezolvam in cit mai multe limbaje posibile, si vedem la fata locului diferenta intre limaje?

Propun urmatorul exercitiu: Integrarea numerica prin metoda trapezelor. Asta e un exercitiu pe care fiecare elev de liceu ar putea sa il rezolve.

Acest exercitiu arata cum se folosesc functii si proceduri (adica functia de integrat si procedura de integrare sa fie declarate printr-o functie de sine statatoare), ciclul repetitiv (care o fi el) , si basic IO.

Teoria din spatele integrarii numerice e in wikipedia: http://en.wikipedia.org/wiki/Trapezoidal_rule

Vom folosi ecuatia:

[tex] \int _{a}^{b}\!f \left( x \right) {dx} = \frac{b-a}{n} \left( \frac{f (a)+f(b)}{2}+\sum_{k=1}^{N} f \left(a+k \frac{b-a}{n}\right) \right)[/tex] 

Datele de intrare ale problemei:
1) functia de integrare f (exemplu : f(x) = x^3 )
2) limitele de integrare a si  b (exemplu: a=2 b=4)
3) numarul de pasi de integrare n (exemplu n=1000)

Propun sa se posteze codul numai daca codul e testat ca merge si ca bonul sa ni se inedice de unde putem downloada mediul respectiv de programare free daca e posibil.

Pseudocodul ar fi f. simplu:
1. defineste functia dfe integrat f(x)
2. defineste functia ce integreaza trapeze(f a b n)
3. calculeza integrala pentru un caz concret.


Scopul postarii e sa vedem la fata locului diferenta intre limbaje pe un caz concret.

Voi reveni cu rezolvarea pe un limbaj concret.

b12mihai

#1
Citat[tex]\int _{a}^{b}\!f \left( x \right) {dx} = \frac{b-a}{n} \left( \frac{f (a)+f(b)}{2}+\sum_{k=1}^{N} f \left(a+k \frac{b-a}{n}\right) \right) [/tex] 

Vad ca pe Wikipedia e putin altfel: [tex] \int _{a}^{b}\!f \left( x \right) {dx} = \frac{b-a}{n} \left( \frac{f (a)+f(b)}{2}+\sum_{k=1}^{n-1} f \left(a+k \frac{b-a}{n}\right) \right)[/tex] adica suma e pana la n-1, nu pana la n...Si "ochiometric" pe grafic, sa zic asa, e pana la n-1 ca al n-lea termen al sumei din paranteza este f(a) + f(b) / 2 .

Oricum interesanta si utila regula, nu am auzit niciodata de ea, cunosti vreun site unde este si demonstrata analitic (nu numai grafic), sau explicata mai riguros?

Update, pe acelasi link de pe wikipedia am gasit implementarea in C a regulii trapezului: http://www.blikbit.com/article/42 . E buna sa ii ajute pe cei care cunosc limbajul si nu reusesc sa ii dea de cap singuri.
Fiecare are scopul lui in lumea asta nebuna.

florin_try

Multumesc pentru corectie.

Iata cum arata ar arata in lisp:

(defun f(x)  (* x x x) ) ; defineste functia f(x) = x^3

(defun trapez_int (f a b n)  ; asta defineste trapezele
  (let ((step (/  (- b a)  n)) ; step = (a-b)/n   
         (s0 (/  (+ (funcall f a) (funcall f b)) 2)) ; s0 = fa+fb/2
         (x a))  ; x = a
    (loop for i from 1 to (1- n) do ; for (i=0 i<n i++){}
          (incf x step) ;x=x+h
          (incf s0 (funcall f x))
     ) ; s0 = s0+f(x)
    (* s0 step ) ; trapez_int=s0*h
))

Ca sa o calculez i-am dat:

(trapez_int f 2 4 100) ; asa accesez integrarea de la 2 la 4 in 100 pasi.

REZULTATUL : 150003/2500

(trapez_int f 2 4 1000)  ; (in o mie pasi integrare)
rezultatul: 15000003/250000

Ca sa obtin rezultatul ca numar real si nu rational am inmultit totul cu 1.0 adica:

(* (trapez_int 'f 2 4 1000) 1.0)
REZULTATUL : 60.000012


-------

Am folosit lisp corman (www.cormanlisp.com/download.html ) care e free pentru 30 zile.



florin_try


Iata-l si in javascript / html.

Tot ce trebuie facut e de salvat fisierul cu continutul de mai jos in extensia .html si de incarcat intr-un browser
textul cu rosu e scriptul de calcul
textul cu bold albastru a apelul propriu zis al functiei de integrare. Ultimul numar e numarul de pasi de incarcare.
Cu o mie pasi integrare imi da: 60.00001199999256
cu o suta pasi integrare imi da: 60.00120000000006


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=windows-1250">
  <meta name="generator" content="PSPad editor, www.pspad.com">
  <title> first test html/javascript </title>
  </head>
  <body>
 
  <div id="results"></div>

  <script>
   function f(x) { return x*x*x }
   function trapez_int(f,a,b,n){
     var step = (b-a)/n
     var s0 = (f(a)+f(b))/2
     var x=a;
     for (var i=1;i<n;i++) {
      x += step
      s0 += f(x)
     }
     return s0*step;
   }
   //alert('Int='+trapez_int(f,2,4,1000));
  </script>
 
  <script>
    x=document.getElementById('results')
x.innerHTML='Integral='+ trapez_int(f,2,4,1000)
    document.getElementById('results').style.fontSize=26;
  </script>

  </body>
</html>

florin_try

Iata-l si in java. Sunt mai multe moduri de a programa asta; am ales pe cel mai 'rudimentar'

Pentru java am instalat netbeansul ca mediu de programare ( http://netbeans.org/ ) si desigur aveam java instalat
(e free de la sun: http://www.java.com/en/download/index.jsp )
La 100 pasi integrare mi-a dat: Int=60.00120000000006
La 1000  pasi ntegrare a dat Int=60.00001199999256
Pasii de integrare se modifica de la textul cu albastru, ultima valoare . Nu mi-am atut capul sa le mai citesc de la consola.

codul
---------------------

package javaapplication11;

public class Main {

    public static void main(String[] args) {
        System.out.print("Int="+trapez_int( 2, 4, 100) );
    }

   private static double f( double x) { return x*x*x; };

   private static double trapez_int( double a, double b, int n) {
     double step = (b-a)/n;
     double s0 = (f(a)+f(b))/2;
     double x=a;
     for (int i=1;i<n;i++){
        x+=step;
        s0+=f(x);
     }
     return s0*step;
   };
}

florin_try


Iata si versiiunea fortran 90.
Am folosit un compilator vechi si free. ( http://gcc.gnu.org/fortran/ ) . Intel da o luna ifort-ul free.

Ar trebui sa fie usor de urmarit diferenta de sintaxa intre acest limbaj "verbose" si cele C-like.
trapeze_int putea fi o functie dar am pus-o ca subrutine pentru a arata diferenta intre functii si subrutine in fortran.
In C++ o subrutina ar fi o functie void.
Poate cineva pentru comparatie sa ne arate cum ar fi acest cod in defunctul fortran 77? Sintaxa lui fortran77 e total diferita de fortran90.
De fapt fortranul a murit si supravietuit in acelasi timp cu tranzitia de la fortran 77 catre fortran 90.


-------------------------------------------

module operatii
implicit none;
public :: f;
public :: trapeze_int;
contains
real(8 ) function f(x)
   real(8 ) x
   f = x*x*x
end function f

subroutine trapeze_int(a,b,n, int)
   real(8 ) , intent(IN) :: a,b
   integer, intent(IN) :: n
   real(8 ) , intent(OUT) :: int
   real(8 ) s0,step,x
   integer i;

   step = (b-a)/dble(n);
   s0 = (f(a)+f(b))*0.5d0;
   x=a;
   do i=1,n-1
      x=x+step;
     s0=s0 + f(x)
   enddo 
   int = s0*step
end subroutine trapeze_int   
end module operatii

program main
use operatii, only : trapeze_int
implicit none
real(8 ) integrala

   call trapeze_int(2.0d0,4.0d0,1000, integrala)
   print*,'int = ',integrala;
end program main;

florin_try

Iata-l si in windows-powershell. Windows powershelul e un limbaj de scriptare ce poate fi downlaodad de la microsoft
( http://www.microsoft.com/windowsserver2003/technologies/management/powershell/download.mspx )
Recomandabil e powershell 2. Cine are windows si nu are powershell are nevoie de un baross ca sa dea cu el in laptop/computer.
Limbajul a fost privit cu entuziasm, e foarte apropiat de c-shelul linuxului (cine a folosit linux stie despre ce e vorba)

Aici insa am avut unele probleme, desi nu vad nici o eroare in script obtin resultate usor diferite de cele aterioare
La 100 pasi integrare obtin: 59.3612000000001
La 1000 pasi integrare obtin: 59.9360119999926
Aparent am mincat un pas????
Evident windows-poweshell nu e pentru acest gen de aplicatie.... Dar e nostim.

Apelul functiei de integrare e cu albastru. Daca incercati trapeze_int(2,4,100) nu va merge desi intuitiv e de neinteles de ce nu merge (e totusi produs microsoft .... nu se dezminte). 


-------------------------------


function f ([double]$x){ $x*$x*$x}

function trapez_int ([double]$a , [double]$b , [double]$n) {
$step = ($b-$a)/$n
$s0 = (f($a) + f($b))/2
$x=$a
for ($i=1;$i -le $n-1;$i++){
   $x += $step
   $s0 += f($x)
}
$step*$s0
}

trapez_int 2 4 1000

florin_try


In postez si in c-chell (linux/unix) in speranta ca alti cititori vor posta in alte limbaje sau vor gasi util ce e aici.

In windows c-shelul se poate poate instala cu cyg-win ( http://www.cygwin.com/ )
Pentru 100 pasi integrare a durat cam 2 minute iar la 1000 pasi integrare a durat ... mult mai mult.
Asta e diferenta intre script si program compilat.

Bineinteles c-shelul nu e pentru acest gen de aplicatie, dar modul cum l-am scris poate ajuta pe cineva care are de scris un script in linux care sa repete niste operatiuni.
------


#!/bin/bash
PREC=16 # global bariable it is the precition

function f() {
a=`echo "scale=$PREC; $1 * $1 * $1"|bc -l` #f(x) = x*x*x
echo $a
}

function trapez_int() {
step=`echo "scale=$PREC; ($2 - $1) /$3"|bc -l` # step = (b-a)/n
f2=`f $2`  # f2 = f(b)
f1=`f $1`  # f1 = f(a)
s0=`echo "scale=$PREC; ($f2 + $f1) /2"|bc -l` # s0=(f(b)+f(a))/2
x=$1 # x=a
for i in  $(seq 1 $(($3-1)))
do
x=`echo "$x + $step"|bc -l`  # x = x + step
fx=`f $x` # fx = f(x)
s0=`echo "$s0 + $fx"|bc -l`  # s0 = s0 + f(x)
done
echo `echo "scale=$PREC; $s0 * $step"|bc -l`
}


a=`trapez_int 2. 4. 1000`
echo $a

# 100 = 60.0012000000000000
# 1000 60.0000120000000000

Adi

Wow, felicitari! Chiar e foarte util sa fie rezolvat un exemplu concret in mai multe limbaje de programare. Tu le-ai programat in toate sau l-ai gasit facut undeva? In orice caz, felicitari pentru idee si pentru realizare!
Pagina personala: http://adrianbuzatu.ro

florin_try

#9
Pai programare e jobul meu. 
Cineva a mentionat bine ca e diferenta intre programator si informatician.
Eu intru in prima categorie, dar ma descurc.
Am scris efectiv micul cod in limbajele de mai sus (am insa experienta anterioara in fiecare din ele) si am indicat  si ce mediu am folosit si de unde l-am downloadat si ce rezultat am obtinut.

Incepuse la alt thread o discutie de principiu despre limbaje de programare insa cred ca mai ilustrativ ar fi un caz simplu tradus in diferse limbaje, cu mentiunea ca adevarata diferenta intre limbaje se simte abia la programele complexe.

Hopefully unii cititori vor posta si in alte limbaje.


florin_try

#10
 Iata si versiunea mapple. Traducerea e ad-literam din celelalte limbaje. Apelul functiei e cu albastru
Este desigur sinistru sa programezi in mapple cum sa calculezi prin metoda trapezelor cind mapple - ul poate calcula
integrale simbolic printr-o simpla comanda >int(f(x),x=A..B)
Mapple ul nu prea e free dar o versiune demo pe termen limitat se poaet descarca de la:
http://www.maplesoft.com/products/Maple/students/index.aspx

Codul de mai jos poate fi calculat intr-o singura comanda:
> evalf(int(x^3,x=2..4));
insa pentru c pentru a arata in principiu cum se foloseste o functie/procedura si ciclu repetitiv in mapple vezi mai jos:

EDIT: mapple-ul traduce automat cod din sintaxa 'mapple' in C, fortran, si latex.
-----------------

> f:=proc(x)
>    x*x*x
> end proc;
               

> trapez_int:=proc(a, b, n)
>    local step, s0, x, i;
>    step := (b-a)/n;
>    s0 := (f(b)+f(a))/2;
>    x:=a;
>    for i from 1 to n-1 do
>      x:=x+step;
>      s0:=s0+f(x);
>    od;
>    step*s0;
> end proc;

> trapez_int(2,4,1000);


AlexandruLazar

N-am nicio implementare LISP pe calculatorul de pe care postez (de fapt am dar trebui sa dau reboot si pe urma o sa uit), doar o idee rapida: ca sa scapi de inmultirea urata cu 1.0 de la sfarsitul functiei trapez_int, ai putea sa initializezi setul de valori ale functiei direct cu valori float (adica in loc de a o apela de la 2 la 4 in 100 de pasi, sa o apelezi de la 2.0 la 4.0). Anumite implementari (de exemplu SBCL) te lasa sa specifici explicit tipul variabilei dar nu stiu exact cat e de portabil.

florin_try

#12
 Multumesc pentru completare.

S-a deschis azi o rubrica pe forum de "Grafica pe calculatoare". M-am jucat in trecut un pic cu pov-ray-ul ( www.povray.org ) , si am postat
la acea rubrica un mic script de pus niste sfere, dar m-am gindit ca ar fi nostim sa rezolv o integrala prin metoda de mai sus chiar si in pov-ray.

Poate fi verificat copiind scriptul de mai jos in editorul pov-rayului si dind comanda sa faca "rendering" adica sa construiasca o imagine.
In loc sa construiasca imagine, scriptul pov-ray de mai jos va calcula o integrala prin metoda trapezelor si va tipari rezultatul intr-un anumit mod .... artistic? (la un anumit unghi).

Integrala e calculata intr-un macro si returnata in variabila tt. functia e declarata ca o functie normala. (se poate vedea diferenta intre functie si macro in pov-ray).

Desigur pov-ray-ul nu e pentru a calcula integrale ci pentru a "render" obiecte tridimensionale din obiecte geometrice, functii, meshuri, spline, etc.


Insa iata scriptul pov-ray pentru integrare numerica (cu rosu e macro ul de integrare iar cu albastru e apelul macroului):
------------------------------------------------------------

#declare f=function(x) {  x*x*x }           

#macro trapez_int(f,a,b,n,tt)
  #declare step = (b-a)/n ;
  #declare s0 = (f(a)+f(b))/2.0;
  #declare dx = a;       
  #declare i = 1;
  #while( i< n )
     #declare dx = dx + step;
     #declare s0 = s0 + f(dx);
     #declare i = i + 1;
  #end
  #declare tt = step * s0;
#end



#include "colors.inc"
  camera {
    location <25, 10, -15>
    look_at 1
    angle 20
  }
  light_source { <500,500,-1000> White }
  plane {
    y,0
    pigment { checker Silver White }
  }



#declare tt=1;   
trapez_int(f,2,4,100,tt)
text {
    ttf "timrom.ttf" concat("Integrala=",str(tt,0,8)) 1, 0
    pigment { Red }
  }