Avatar billede CDJ Nybegynder
17. marts 2011 - 20:40 Der er 6 kommentarer og
1 løsning

BCMath Arbitrary Precision Mathematics

Hej folkens,

Jeg forsøger at lave en kemisk beregning i PHP - af pH-værdien af vandige opløsninger af syrer i meget lave koncentrationer. De meget lave koncentrationer medfører, at tallene vil være meget små - tilsyneladende mindre end PHP umiddelbart kan regne med dem. Mit script ser ud som følgende:

$cs = pow(10, -8);
$ks = pow(10, -7);
$kv = pow(10, -14);

$langt_udtryk = pow(sqrt(((2 * pow($ks, 2) * pow($kv, 2)) / 27) - ((pow($ks, 4) * pow($cs, 2)) / 108) - ((5 * pow($ks, 3) * $kv * $cs) / 27) - ((pow($ks, 3) * pow($cs, 3)) / 27) - ((pow($ks, 4) * $kv) / 27) - ((pow($ks, 2) * $kv * pow($cs, 2)) / 9) - (($ks * pow($kv, 2) * $cs) / 9) - (pow($kv, 3) / 27)) - (pow($ks, 3) / 27) - ((pow($ks, 2) * $cs) / 6) + (($ks * $kv) / 3), (1 / 3));
var_dump($langt_udtryk);

$x = (((pow($ks, 2) / 9) + (($cs * $ks) / 3) + ($kv / 3)) / $langt_udtryk) - ($ks / 3) + $langt_udtryk;
var_dump($x);

$ph = -log10($x);
var_dump($ph);

Og outputtet er følgende:

Langt udtryk: float(NAN)
x: float(NAN)
pH: float(NAN)

Hvis jeg derimod erstatter sqrt i ovenstående udtryk med bcsqrt er outputtet følgende:

Langt udtryk: float(6.53924680941E-8)
x: float(1.05122255286E-7)
pH: float(6.97830533036)

Jeg har lavet den samme beregning manuelt med henblik på at kontrollere resultatet - og jeg får følgende resultater:

x = 1,025 * 10^-7
pH = 6,989

Afvigelsen ude på 2. decimal skyldes formodentlig blot afrunding, så det må siges at være acceptabelt. Så langt, så godt - jeg fik noget der lignede det, jeg gerne ville have.

Derimod bliver det rigtig mystisk, når jeg giver $ks andre værdier - eksempelvis:

$ks = 1.738 * pow(10, -5);

Nu får jeg nemlig - selv ved brug af bcsqrt() - følgende output:

Langt udtryk: float(NAN)
x: float(NAN)
pH: float(NAN)

Ifølge mine manuelle beregninger burde output være:

x = 1,051 * 10^-7
pH = 6,978

Er der nogen der ved, hvad det kan skyldes?

På forhånd mange tak. Al hjælp er værdsat!
Avatar billede CDJ Nybegynder
17. marts 2011 - 20:41 #1
Lige for god ordens skyld et par links - det glemte jeg lige:

http://dk.php.net/bc
http://dk.php.net/bcsqrt
Avatar billede intenz Novice
18. marts 2011 - 10:53 #2
Jeg testede lige dit script. Den udregning du forsøger at tage sqrt af, er et negativt tal. Af samme grund kan man selvfølgelig ikke beregne sqrt :) Derfor får du NAN fejlen (not a number).

Enten er formlen forkert (hvilket jeg ikke er i stand til at sige :p), ellers kan du tage den absolutte værdi af tallet.
http://php.net/manual/en/function.abs.php
Avatar billede CDJ Nybegynder
18. marts 2011 - 11:47 #3
@intenz: Mange tak for dit svar. Du har selvfølgelig ret - det er i PHP ikke umiddelbart muligt at tage kvadratroden af et negativt tal, da PHP ikke kan håndtere imaginære tal. Du får selvfølgelig point for din observation - og det i øvrigt helt korrekte svar på, hvorfor output er NAN.

Det afføder dog et nyt problem. Formlen er nemlig korrekt. Jeg kan desværre ikke blot efter forgodtbefindende ændre fortegn - hvorfor det desværre ikke er en mulighed at tage den absolutte værdi af tallet. Min manuelle kontrolberegning er udført i MathCad - som også kan regne med komplekse (dvs. imaginære) tal. Kontrolberegningen i MathCad viser, at "langt udtryk" i MathCad bliver imaginær, hvis jeg udskriver værdien:

Langt udtryk = 2,142 * 10^-7 + 1,24i * 10^-7

Og i PHP:
Langt udtryk = float(NAN)

Da dette blot er en midlertidig variabel (som er til for overskuelighedens skyld) er det ikke problematisk at tallet bliver imaginært, idet slutresultaterne (x og pH) bliver fine reelle tal:

x = 1,051 * 10^-7
pH = 6,978

Mit problem er således ikke af matematisk karakter - at jeg får et imaginært tal. Mit problem er derimod - så vidt jeg nu kan se - at PHP ikke kan håndtere imaginære tal. Jeg har forgæves kigget på nogle classes, men uden helt at finde hvad jeg søgte.

Men foreløbig mange tak! Yderligere input er meget velkomne.
Avatar billede intenz Novice
18. marts 2011 - 14:13 #4
Det kan være du er faldet over disse classes allerede, men jeg kunne finde to potentialle muligheder.

http://www.phpclasses.org/package/2844-PHP-Perform-arithmetic-operations-with-complex-numbers.html

http://pear.php.net/package/Math_Complex
Avatar billede CDJ Nybegynder
19. marts 2011 - 15:19 #5
@intenz: Tak for tippet. Jeg har i mellemtiden set nærmere på de to muligheder - og min umiddelbare konklusion er, at førstnævnte ser ud til at være lettest at gå til. Der ser ud til at være et væld af muligheder i PEAR, men den er temmelig dårligt dokumenteret - og da jeg endnu ikke har særlig meget erfaring med objektorienteret programmering vil jeg i første omgang ty til den mest veldokumenterede. Der medfølger nemlig bl.a. en sample.php - med en række eksempler på brug af klassen. Jeg melder tilbage, når jeg har gjort mig nogle erfaringer. Foreløbig mange tak!
Avatar billede CDJ Nybegynder
19. marts 2011 - 21:36 #6
Det ser umiddelbart brugbart ud - jeg er i stand til at udføre simple beregninger ved brug af den første PHP-klasse. Så langt, så godt. Desværre kommer jeg nu matematisk til kort, idet klassen ikke indeholder nogen potensfunktion - svarende til PHP's indbyggede pow-funktion, som desværre kun kan håndtere reelle tal. Jeg kunne ikke umiddelbart google mig til svaret på, hvad z^(1/3) er.
Avatar billede CDJ Nybegynder
20. marts 2011 - 22:27 #7
Tak for alle indspark - jeg ville blot lige lade jer vide, at problemet var løst.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester