Velena Skrevet 3. april 2008 Del Skrevet 3. april 2008 Her var det voldsomt aktivt ja. Uansett har jeg startet på et nytt program som blant annet skal kunne løse 3djegradslikninger av typen aX^3 + bX^2 + cX + d. Problemet jeg ha støtt på, er at kalkulasjonene koden utfører har skuffende lav nøyaktighet. I de bese tilfellene dreier det seg om hundredeler, men jeg har støtt på situasjoner hvor koden har vært hele 3 enheter feil. her er koden jeg har laget : namespace CubicEquation { public partial class Form1 : Form { public double ax; public double abx; public double abx2; public double acx; public double bx; public double bcx; public double cx; public double dx; public double FF; public double GG; public double HH; public double II; public double JJ; public double KK; public double LL; public double MM; public double NN; public double PP; public double RR; public double SS; public double TT; public double UU; public double X1; public double X2; public double X3; public double JJx; public double JJx2; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { ax = double.Parse(textBox1.Text.ToString()); bx = double.Parse(textBox2.Text.ToString()); cx = double.Parse(textBox3.Text.ToString()); dx = double.Parse(textBox4.Text.ToString()); acx = (3 * cx) / ax; abx = (bx * bx) / (ax * ax); FF = (acx - abx) / 3; MessageBox.Show(FF.ToString()); // Disse er lagt til for å finne eventuelle feil i koden ( bruker eksemplene på [url="http://www.1728.com/cubic2.htm"]http://www.1728.com/cubic2.htm[/url] til referanse) abx2 = (2 * bx * bx * bx) / (ax * ax * ax); bcx = (9 * bx * cx) / (ax * ax); GG = (abx - bcx + ((27 * dx) / ax)) / 27; MessageBox.Show(GG.ToString()); HH = ((GG*GG) / 4) + ((FF * FF * FF) / 27); MessageBox.Show(HH.ToString()); if (HH <= 0) { // Nedenfor er metoden som brukes når h er mindre enn eller lik 0 II = Math.Pow((((GG * GG) / 4) - HH), 0.5); MessageBox.Show(II.ToString()); JJ = Math.Pow(II, 0.33333333333333334);// jeg skriver 0.333333333333334 istedet for 1/3 pga at det skjedde en feil når jeg satte det andre argumentet til en brøk MessageBox.Show(JJ.ToString()); KK = Math.Acos(-(GG / (2 * II))); MessageBox.Show(KK.ToString()); LL = JJ * -1; MessageBox.Show(LL.ToString()); MM = Math.Cos(KK / 3); MessageBox.Show(MM.ToString()); NN = Math.Sqrt(3.0) * Math.Sin(KK / 3); MessageBox.Show(NN.ToString()); PP = (bx / (3 * ax)) * -1; MessageBox.Show(PP.ToString()); X1 = 2 * JJ * Math.Cos(KK / 3) - (bx / (3 * ax)); X2 = LL * (MM + NN) + PP; X3 = LL * (MM - NN) + PP; label1.Text = X1.ToString(); label2.Text = X2.ToString(); label3.Text = X3.ToString(); } else if (HH == 0 && FF == 0 && GG == 0) { // Nedenfor er metoden som brukes når h f og g alle er 0 ( denne koden kjøres, så vidt jeg vet, aldri. Regner med at det er pga at koden ikke er 100% nøyaktig) double ax2 = Math.Pow((dx / ax), 0.3333333333333333333334); MessageBox.Show(aX.ToString()); X1 = ax2 * -1; X2 = X1; X3 = X2; label1.Text = X1.ToString(); label2.Text = X2.ToString(); label3.Text = X3.ToString(); } else if (HH >= 0) { // ----------- " " ------------------- h er større enn eller lik 0. II = Math.Pow((((GG * GG) / 4) - HH), 0.5); MessageBox.Show(II.ToString()); RR = -(GG / 2) + Math.Pow(HH, 0.5); MessageBox.Show(RR.ToString()); SS = Math.Pow(RR, 0.33333333333333333334) ; MessageBox.Show(SS.ToString()); TT = - (GG/2) - Math.Pow(HH, 0.5); MessageBox.Show(TT.ToString()); UU = Math.Pow(TT, 0.333333333333333333333333334); MessageBox.Show(UU.ToString()); X1 = (SS + UU) - (bx / 3 * ax); X2 = -(SS + UU) / 2 - (bx / 3 * ax) + II * (SS - UU) * Math.Pow(3, 0.3333333333333333334) / 2; X3 = -(SS + UU) / 2 - (bx / 3 * ax) - II * (SS - UU) * Math.Pow(3, 0.3333333333333333334) / 2; label1.Text = X1.ToString(); label2.Text = X2.ToString();//gir foreløping resultatet NaN (gjetter på at det er fordi tallet er imaginært) label3.Text = X3.ToString();// samme med dette } } } } Hvis noen lurer er den basert på formlene jeg fant på denne siden:http://www.1728.com/cubic2.htm Når jeg sier at koden min regner feil, går jeg ut ifra at resultatene jeg får på siden er korrekt. La meg gi et eksempel: Når jeg bruker likningen 2x^3 - 4x^2 - 22x + 24 = 0 gir siden resultatene X1 =4 X2= -3 X3= 1 , mens min kode gir X1=3.96411 X2 = - 3.02618 X3 =1.06206 Hva er det som forårsaker dette? Som alltid: Takk på forhånd :!: . Lenke til kommentar
blackbrrd Skrevet 3. april 2008 Del Skrevet 3. april 2008 (endret) Double har presisjonsfeil i det 15. eller 16. sifferet. Ganger du sammen to doubles så kan du ende opp med ett siffer mindre presisjon. I java så hadde jeg benyttet klassen BigDecimal hvis jeg ønsket nøyaktighet. Der kan du spesifisere f.eks 1000 desimalers nøyaktighet. Dette vil være svært tregt. (tusenvis av ganger tregere enn med double) Endret 3. april 2008 av blackbrrd Lenke til kommentar
Manfred Skrevet 3. april 2008 Del Skrevet 3. april 2008 sånn uten at jeg skal uttale meg skråsikkert her, så er vel dette en god måte å få dårlig presisjon på: double a = (2 * dbl); //her multipliserer du en double med en int ...du ville vel da fått bedre presisjon ved å si: double a = (2.000 * dbl); Noen som har innspill på dette? Lenke til kommentar
GeirGrusom Skrevet 4. april 2008 Del Skrevet 4. april 2008 Tror ikke det spiller noen rolle om du multipliserer med double eller int, siden integer vil bli konvertert til 80-bit allikevel. JJ = Math.Pow(II, 0.33333333333333334) Problemet ditt kan ha vært at du dividerte med 2 heltall altså 1/3 = 0, 1 % 3 = 3 hvis du forstår prøv dette istedet JJ = Math.Pow(II, 1.0 / 3.0) For større presisjon, kan du bruke decimal istedet, den er 128-bit, men uheldigvis er ikke Math.Pow laget for decimal. Lenke til kommentar
Velena Skrevet 4. april 2008 Forfatter Del Skrevet 4. april 2008 (endret) Tror ikke det spiller noen rolle om du multipliserer med double eller int, siden integer vil bli konvertert til 80-bit allikevel. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace CubicEquation { public partial class Form1 : Form { // Nå er så mange som mulig av variablene gjort om til Decimal public decimal ax; public decimal abx; public decimal abx2; public decimal acx; public decimal adx; public decimal bx; public decimal bcx; public decimal cx; public decimal dx; public decimal FF; public decimal GG; public decimal HH; public double II; public decimal IIcon; public decimal JJcon; public double JJ; public decimal KKcon; public double KK; public double LL; public double MM; public double NN; public decimal PPcon; public double PP; public decimal RRcon; public double RR; public double SS; public decimal TTcon; public double TT; public double UU; public decimal X1con; public double X1; public double X2; public double X3; public double JJx; public double JJx2; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { ax = decimal.Parse(textBox1.Text.ToString()); bx = decimal.Parse(textBox2.Text.ToString()); cx = decimal.Parse(textBox3.Text.ToString()); dx = decimal.Parse(textBox4.Text.ToString()); acx = (3 * cx) / ax; abx = (bx * bx) / (ax * ax); FF = (acx - abx) / 3; ; MessageBox.Show(FF.ToString()); abx2 = (2 * bx * bx * bx) / (ax * ax * ax); bcx = (9 * bx * cx) / (ax * ax); GG = (abx - bcx + ((27 * dx) / ax)) / 27; MessageBox.Show(GG.ToString()); HH = ((GG*GG) / 4) + ((FF * FF * FF) / 27); MessageBox.Show(HH.ToString()); if (HH <= 0) { IIcon= ((GG*GG)/4) - HH; //Gjør dette pga Math.Pow ikke godtar decimal input II = Math.Pow(double.Parse(IIcon.ToString()), (1.0/2.0)); MessageBox.Show(II.ToString()); JJ = Math.Pow(II, (1.0/3.0)); MessageBox.Show(JJ.ToString()); KKcon = -(GG/(2*decimal.Parse(II.ToString()))); KK = Math.Acos(double.Parse(KKcon.ToString())); MessageBox.Show(KK.ToString()); LL = JJ * -1; MessageBox.Show(LL.ToString()); MM = Math.Cos(KK / 3); MessageBox.Show(MM.ToString()); NN = Math.Sqrt(3.0) * Math.Sin(KK / 3); MessageBox.Show(NN.ToString()); PPcon = (bx / (3 * ax)) * -1; PP = double.Parse(PPcon.ToString()) ; MessageBox.Show(PP.ToString()); X1con = bx / (3 * ax); X1 = 2 * JJ * Math.Cos(KK / 3) - double.Parse(X1con.ToString()); X2 = LL * (MM + NN) + PP; X3 = LL * (MM - NN) + PP; label1.Text = X1.ToString(); label2.Text = X2.ToString(); label3.Text = X3.ToString(); } else if (HH == 0 && FF == 0 && GG == 0) { adx = dx / ax; double aaa = Math.Pow(double.Parse(adx.ToString()), (1.0/3.0)); MessageBox.Show(aaa.ToString()); X1 = aaa * -1; X2 = X1; X3 = X2; label1.Text = X1.ToString(); label2.Text = X2.ToString(); label3.Text = X3.ToString(); } else if (HH >= 0) { IIcon = ((GG * GG) / 4) - HH; II = Math.Pow(double.Parse(IIcon.ToString()), 0.5); MessageBox.Show(II.ToString()); RRcon = -(GG / 2); RR = double.Parse(RRcon.ToString()) + Math.Pow(double.Parse(HH.ToString()), 0.5); MessageBox.Show(RR.ToString()); SS = Math.Pow(RR, (1.0/3.0)) ; MessageBox.Show(SS.ToString()); TTcon = -(GG / 2); TT = double.Parse(TTcon.ToString()) - Math.Pow(double.Parse(HH.ToString()), 0.5); MessageBox.Show(TT.ToString()); UU = Math.Pow(TT, (1.0/3.0)); MessageBox.Show(UU.ToString()); X1con = ((bx / 3) * ax); X1 = (SS + UU) - double.Parse(X1con.ToString()); X2 = -(SS + UU) / 2 - double.Parse(X1con.ToString()) + II * (SS - UU) * Math.Pow(3, (1.0/3.0)) / 2; X3 = -(SS + UU) / 2 - double.Parse(X1con.ToString()) - II * (SS - UU) * Math.Pow(3, (1.0 / 3.0)) / 2; label1.Text = X1.ToString(); label2.Text = X2.ToString(); label3.Text = X3.ToString(); } } } } Endret 4. april 2008 av Velena Lenke til kommentar
Manfred Skrevet 4. april 2008 Del Skrevet 4. april 2008 Skrive en Pow-funksjon selv, som gjør det da ^^ Lenke til kommentar
GeirGrusom Skrevet 4. april 2008 Del Skrevet 4. april 2008 Skrive en Pow-funksjon selv, som gjør det da ^^ Eller kubikkrot som er det han egentlig er ute etter allikevel ^^ Og da trenger han bare bruke naturlige logaritmer for å løse det. Lenke til kommentar
Velena Skrevet 4. april 2008 Forfatter Del Skrevet 4. april 2008 Jeg må si at jeg ikke er kjent med metoden som du foreslår. Hva er "exp" og "In"? Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå