Den forstod jeg ikke... VC# genkender ikke java i 'using java', og jeg kan ikke finde vjslib.dll på nogen lister, når jeg vælger at tilføje en reference (hvis det er det, jeg skal) - kan du forklare, hvad der er, jeg har misforstået? Uh, jeg er godt nok lidt af en programmeringsrookie.
ARGH! Det var god grænseløst irriterende! Eksperten er begyndt at slette mine meddelelser - når jeg poster dem, kommer der intet frem i tråden, og tekstboksen bliver tømt.
Anyway, here we go again:
Et par spørgsmål: 1) Hvordan konverterer jeg lettest standardklasser til BigInteger eller BigDecimal? Jeg har leget med 'new BigInteger(n)', hvor n f.eks. er short/int/long - det virker men er meget besværligt. 2) Jeg får fejl ved operatorer som '<' og '+=' mellem BigIntegers... Hvorfor?
pow er i Java 1.5 men J# implementerer (det meste af) Java 1.1
så du må multiplicere manuelt
Synes godt om
Slettet bruger
01. november 2008 - 01:57#19
Tak og undskyld, jeg lige flamede Eksperten - for det var denne gang mig, der postede der forkerte sted... Hvilket du forhåbentligt opdagede :) Jeg må prøve med en løkke og multiplikation.
Synes godt om
Slettet bruger
02. november 2008 - 18:20#20
Jeg har et (nyt) problem!
"pow er i Java 1.5 men J# implementerer (det meste af) Java 1.1 så du må multiplicere manuelt"
Det gik også fint i et stykke tid - men nu har jeg bemærket, at jeg skal opløfte en værdi i et ulige tal. Hvordan kan jeg manuelt gøre dette, og er der virkelig slet ingen mulighed for at anvende en eksisterende pow-metode?
Uha, ja, det er godt at kunne sin matematik :P Mange tak... Jeg roder videre med det!
Synes godt om
Slettet bruger
25. november 2008 - 15:57#29
Hm. Jeg har forsøgt at lave en enklede Chudnovsky-algoritme med C#'s indbyggede klasser...
using System; using System.Collections.Generic; using System.Linq; using System.Text;
namespace PiTestChudnovsky { class SimpleChudnovsky { public long Ticks = 0; public long Precision = 0; public double Result;
public SimpleChudnovsky(long n) { Calculate(n); }
public double Calculate(long n) { long ticks = DateTime.Now.Ticks; Precision = n; double result = 0; for (long k = 0; k <= n; k++) result += Math.Pow((double)-1, (double)k) * (double)SimpleMath.Faculty(6 * k) * (double)(13591409 + 545140134 * k) / (double)SimpleMath.Faculty(3 * k) / Math.Pow((double)SimpleMath.Faculty(k), (double)3) / Math.Pow((double)640320, (double)(3 * k) + (double)3 / (double)2); Result = 1 / (12 * result); Ticks = DateTime.Now.Ticks - ticks; Console.WriteLine(":" + Result.ToString() + ":"); return Result; } } }
Problemet er bare, at applikationen udskriver :NaN: ved kald! Hvorfor?
Synes godt om
Slettet bruger
25. november 2008 - 15:58#30
Og for lige at hjælpe C# lidt på vej: Result = (double)1 / ((double)12 * result); i stedet for Result = 1 / (12 * result); Men det gør ingen forskel for NaN-problemet :(
public static long Faculty(long n) { if (n==0) return 1; for (long i = n; i > 1; n *= --i) { }; return n; }
Synes godt om
Slettet bruger
26. november 2008 - 23:02#35
Hvad pokker! Jeg havde ingen anelse om, at fakultet 0 giver 1... Kan jeg få dig til at give en matematisk forklaring (hvis den ikke er for omfattende)? PS: Det virker nu :)
Og så har jeg lige et andet spørgsmål samtidig: Samtlige beregninger af antal ticks forløbet under beregninger giver 0. Hvorfor? Jeg har også prøvet med Environment.TickCount (også uden held).
Suk. Wikipedia har en tendens til at gøre matematik besværligt og samtidig alt for enkelt... Måske skulle jeg bare spørge min matematiklærer engang :) Anyway, det andet spørgsmål er vigtigere.
Det lyder meget sandsynligt at dine NaN skyldes for høje tal.
Men men men.
Muligvis har du problemer allerede før det.
Jeg fik problemer allerede med n=4.
Jeg oversatte nemlig koden med check for integer overflow.
Jeg synes at du skulel prøve og slå det til !
Synes godt om
Slettet bruger
27. november 2008 - 15:01#45
Aha :) Jamen glædelig Thanksgiving!
Hvordan tjekker jeg integer overflow?
PS: Projektet begynder i morgen, så jeg skal snart til at kode med de stpre klasser - jeg vil dog gerne anvende nogle lidt bedre integrerede end BigInteger og BigDecimal fra Java, så kender du nogle oplagte alternativer?
Vi fandt jo en .NET big integer klasse en 25 indlæg siden, men det var et problem at finde en big float klasse.
Synes godt om
Slettet bruger
27. november 2008 - 17:40#48
Hmm... Jeg har nu forsøgt at slå samtlige debugging-exceptions til - men jeg fik ingen runtime-fejl. Jeg tror, jeg lader det ligge og kikker på det, hvis problemet genopstår med de nye talklasser.
Jeps, jeg kan godt huske BigInteger-klassen, men jeg håbede, at du var faldet over et alternativ til BigDecimal... Eller at en anden havde en god BigFloat til at ligge. Jeg leder videre!
Tak! Ja, der var sgu overflow (no shit)! Og ja, F# ser meget lovende ud... Jeg kikker lige på det.
Synes godt om
Slettet bruger
27. november 2008 - 19:36#53
Okaj, jeg er forvirret. Hvad er F#? Et nyt sprog? Hvordan kan jeg bruge det i mit program? Kan jeg eventuelt anvende klasserne som ved de Java-baserede BigInteger og BigDecimal? Jeg er pænt forvirret.
Det er sådan OCAML.NET eller en blanding af C# og OCAML.
Ja. Du kan godt bruge F# klasserne fra C#.
BigInt virker perfekt.
BigNum er ikke en BigFloat men en BigRational, hvilket muligvis kan drille lidt.
Her er noget C# kode til at sætte dig igang:
using System; using System.Text;
using Microsoft.FSharp.Math;
namespace E { public static class MyBigNumExts { public static BigInt Factorial(int n) { if(n > 1) { return BigInt.FromInt32(n) * Factorial(n - 1); } else { return BigInt.One; } } public static string MyToString(this BigNum x, int nodec) { StringBuilder sb = new StringBuilder(); BigInt n = x.Numerator; BigInt d = x.Denominator; BigInt intpart = n / d; sb.Append(intpart.ToString()); n = n - intpart * d; sb.Append("."); for (int i = 0; i < nodec; i++) { n = n * BigInt.FromInt32(10); intpart = n / d; sb.Append(intpart.ToString()); n = n - intpart * d; } return sb.ToString(); } } public class Program { public static void Main(string[] args) { for (int i = 0; i < 50; i++) { Console.WriteLine(MyBigNumExts.Factorial(i)); Console.WriteLine(BigInt.Factorial(BigInt.FromInt32(i))); } for (int i = 0; i < 50; i++) { Console.WriteLine(BigNum.PowN(BigNum.FromInt(10), i)); } for (int i = 0; i < 50; i++) { Console.WriteLine(BigNum.PowN(BigNum.FromInt(10), i)); } for (int i = 0; i < 50; i++) { Console.WriteLine(BigNum.PowN(BigNum.FromInt(10), i)); } BigNum onethird = BigNum.One / BigNum.FromInt(3); Console.WriteLine(onethird.ToString()); Console.WriteLine(onethird.MyToString(30)); Console.ReadKey(); } } }
Synes godt om
Slettet bruger
27. november 2008 - 19:56#55
Hvad betyder det, at det er rational? At den gemmer værdier som to forskellige, der så divideres ved fortolkning? Og har det nogen praktisk påvirkning af min kode og/eller præcisionen af den endelige applikation?
Du skal bare lave en ref til FSharp.Core.Dll og lave using.
Synes godt om
Slettet bruger
27. november 2008 - 21:16#61
Med alle de tweaks F#-klasserne kræver for at kunne anvendes til projektet, er det vel lige så smart at vælge Java-klasserne? Eller er der noget, jeg overser?
Nu ved jeg ikke hvor mange tweaks det er. Du har +-*/ og power og factorial. Jeg har givet dig den ToString du vil bruge.
Jeg gætter på at det performer bedre end J# klasserne.
Grunden til det er at F# er noget nyt som bliver udvikler og som der er interesse for. J# var bare noget man skulle have da .NET 1.0 skulle udgives for 6 år siden.
Synes godt om
Slettet bruger
27. november 2008 - 22:27#63
Okay. Så er det nok meget smart at bruge F#... Jeg må lige sætte mig ind i det i morgen formiddag.
F# og OCAML er nok en lidt stor mundfuld til en formiddag ...
Synes godt om
Slettet bruger
28. november 2008 - 08:39#65
O'rly?
Ja. Der er nok at lære... Men det er vel også begrænset, hvad jeg behøver at have kendskab til. Jeg prøver lige at strikke noget sammen...
Synes godt om
Slettet bruger
28. november 2008 - 08:43#66
Bør jeg anvende Chew Keongs BigInteger-klasse eller F#'s udgave? Umidelbart kan jeg finde større funktionalitet i Keongs.
Synes godt om
Slettet bruger
28. november 2008 - 11:27#67
Jeg prøver med Keongs først. Der er en masse features, jeg sikkert kan drage nytte af.
Synes godt om
Slettet bruger
28. november 2008 - 12:48#68
Sådan! Nu er koden skrevet med Keongs BigInteger og F#'s BigNum. Så til debugging!
--- BigNumExtensions ---
using System; using System.Collections.Generic; using System.Linq; using System.Text;
using Microsoft.FSharp.Math;
namespace FChudnovskyTest { public class BigNumExtensions { public static BigNum Power(BigNum x, BigNum y) { if (y == BigNum.FromInt(0)) return BigNum.FromInt(1); else if (y == BigNum.FromInt(1)) return x; else { BigNum z = y / BigNum.FromInt(2); return Power(x, z) * Power(x, y - z); } // This method is needed as the built-in PowN method of the BigNum class does not support decimal numbers as power arguments. // I would like to thank Arne Valhøj for contributing to the design of this method as he wrote the initial code. // See http://www.eksperten.dk/spm/850647 (Danish) for more information. } } }
"An unhandled exception of type 'System.StackOverflowException' occurred in FSharp.Core.dll"
Fejlen trackes til denne linje:
BigNum z = y / BigNum.FromInt(2);
Hvad er der galt?
Synes godt om
Slettet bruger
28. november 2008 - 18:07#69
Slet ingen bud? Jeg skal snart videre med projektet, så alle forslag er kærkomne!
Det er ikke muligt at lave en helt præcis pow funktion for andet end heltal.
Det er ligesom at skrive PI eksakt !
Synes godt om
Slettet bruger
29. november 2008 - 00:40#78
Okaj. Jeg vil dog sige, at det ikke er helt korrekt at påstå, at pi ikke kan skrives eksakt ;) Teknisk set er pi = lin[n->uendelig](n*cos(90-180/n)) en eksakt angivelse... Hvis man altså må kalde en grænseværdi eksakt på et teoretisk plan? Bare spekulationer... Og ligningen har desværre ingen praktisk betydning, da den selv ved ekstremt høje n-værdier kun giver ganske få korrekte cifre.
Anyway: Kan jeg få dig til at give et eksempel på decimal^decimal-metode, der er så præcis som mulig?
Skrive er i denne sammenhæng som rationelle tal, fordi din BigNum er rational og en traditionel floating point også er det (omend lidt mere tricky i format).
Du skal lave enSqrt funktion så kan du bruge 22:57:54.
Jeg tror at du kunne spare dig for meget besvær ved at have valgt en C/C++ bigfloat løsning.
Men anyway:
using System; using System.Text;
using Microsoft.FSharp.Math;
namespace E { public static class MyBigNumExts { public static string MyToString(this BigNum x, int nodec) { StringBuilder sb = new StringBuilder(); BigInt n = x.Numerator; BigInt d = x.Denominator; BigInt intpart = n / d; sb.Append(intpart.ToString()); n = n - intpart * d; sb.Append("."); for (int i = 0; i < nodec; i++) { n = n * BigInt.FromInt32(10); intpart = n / d; sb.Append(intpart.ToString()); n = n - intpart * d; } return sb.ToString(); } public static BigNum Sqrt(BigNum x, int nodec) { BigInt precision = BigInt.Parse("1".PadRight(nodec, '0')); BigNum curr = x / BigNum.Parse("10"); BigNum last; BigNum tmp; do { last = curr; curr = (last + x / last) / BigNum.Parse("2"); tmp = curr - last; if (tmp.IsNegative) tmp = -tmp; } while (tmp.Numerator * precision > tmp.Denominator); return curr; } public static BigNum Pow(BigNum x, BigNum y, int nodec) { BigInt n = y.Numerator; BigInt d = y.Denominator; if (n == BigInt.Zero) { return BigNum.One; } else if (n % d == BigInt.Zero) { if (y.ToString().Length > 9) throw new ArgumentException(y + " is too big an int"); return BigNum.PowN(x, int.Parse(y.ToString())); } else if ((BigInt.Parse("2") * n) % d == BigInt.Zero) {
return Sqrt(x, nodec) * Pow(x, y - BigNum.Parse("1/2"), nodec); } else { throw new ArgumentException(y + " is not int or int + half"); } } } public class Program { public static void Main(string[] args) { Console.WriteLine(MyBigNumExts.Sqrt(BigNum.Parse("4"), 30).MyToString(30)); Console.WriteLine(MyBigNumExts.Sqrt(BigNum.Parse("2"), 30).MyToString(30)); Console.WriteLine(MyBigNumExts.Pow(BigNum.Parse("4"), BigNum.Parse("1/2"), 30).MyToString(30)); Console.WriteLine(MyBigNumExts.Pow(BigNum.Parse("4"), BigNum.Parse("1"), 30).MyToString(30)); Console.WriteLine(MyBigNumExts.Pow(BigNum.Parse("4"), BigNum.Parse("3/2"), 30).MyToString(30)); Console.WriteLine(MyBigNumExts.Pow(BigNum.Parse("4"), BigNum.Parse("2"), 30).MyToString(30)); Console.WriteLine(MyBigNumExts.Pow(BigNum.Parse("2"), BigNum.Parse("1/2"), 30).MyToString(30)); Console.WriteLine(MyBigNumExts.Pow(BigNum.Parse("2"), BigNum.Parse("1"), 30).MyToString(30)); Console.WriteLine(MyBigNumExts.Pow(BigNum.Parse("2"), BigNum.Parse("3/2"), 30).MyToString(30)); Console.WriteLine(MyBigNumExts.Pow(BigNum.Parse("2"), BigNum.Parse("2"), 30).MyToString(30)); Console.ReadKey(); } } }
Synes godt om
Slettet bruger
29. november 2008 - 20:35#82
"Jeg tror at du kunne spare dig for meget besvær ved at have valgt en C/C++ bigfloat løsning."
Altså skrive det hele i C eller C++ med bigfloat-klassen? Den klasse kender jeg ikke... Og jeg har (desværre) ikke tid til at sætte mig ind i C++ :(
Anyway!
Jeg skal vil kun bruge:
public static BigNum Sqrt(BigNum x, int nodec) { BigInt precision = BigInt.Parse("1".PadRight(nodec, '0')); BigNum curr = x / BigNum.Parse("10"); BigNum last; BigNum tmp; do { last = curr; curr = (last + x / last) / BigNum.Parse("2"); tmp = curr - last; if (tmp.IsNegative) tmp = -tmp; } while (tmp.Numerator * precision > tmp.Denominator); return curr; } public static BigNum Pow(BigNum x, BigNum y, int nodec) { BigInt n = y.Numerator; BigInt d = y.Denominator; if (n == BigInt.Zero) { return BigNum.One; } else if (n % d == BigInt.Zero) { if (y.ToString().Length > 9) throw new ArgumentException(y + " is too big an int"); return BigNum.PowN(x, int.Parse(y.ToString())); } else if ((BigInt.Parse("2") * n) % d == BigInt.Zero) {
return Sqrt(x, nodec) * Pow(x, y - BigNum.Parse("1/2"), nodec); } else { throw new ArgumentException(y + " is not int or int + half"); } }
Fordi den udskriver 0.5 som "1/2" (husk at BigNum er brøker internt).
Og jeg antager du vil have PI med decimaler ikke med en 1000 cifret integer over en anden 1000 cifret integer.
Synes godt om
Slettet bruger
30. november 2008 - 10:07#86
Awhaw. Ja. Jeg tænkte ikke lige over, at det godt kan blive svært, at omskrive brøken til et decimaltal ;) Jeg kikker lige på det på et tidspunkt i dag. Tak.
Synes godt om
Slettet bruger
30. november 2008 - 13:04#87
Uhm... Kan jeg så ikke højst få 32767 decimaler udskrevet? Måske skulle jeg forsøge at rode med C++ anyway. Hvilke klasser ville du i så fald anbefale? bigfloat og ... hvad? Og har de klasser alle de nødvendige funktioner indbygget? Hvis det er tilfældet, er det næsten hurtigere for mig at genopfriske C++-konteksten og strikke copy/paste/mod'de min kode til VC++.
Awhawww!!! Ja, så er der vist ingen problemer - bortset fra den overflow error jeg får allerede ved en værdi på 1000. Jeg kikker lige på det...
Synes godt om
Slettet bruger
30. november 2008 - 20:56#92
Og så lige for at være besværlig: Hvilke C++-klasser findes til håndtering af meget store og præcise tal? Måske skulle jeg senere lave et rewrite... Men nu prøver jeg altså det her først uanset hvad.
Okaj :) Tak. Jeg kikker på det hele i morgen tidlig.
Synes godt om
Slettet bruger
01. december 2008 - 10:16#97
Det er da til at blive sindssyg af! Nu er halvdelen af min kode pludselig forsvundet... Det ser ud som om, Windows har besluttet sig for at gendanne mine filer, som de var for flere dage siden. Jeg genskriver lige noget, inden jeg vender tilbage her...
Synes godt om
Slettet bruger
01. december 2008 - 10:17#98
Ah, heldigvis havde jeg åbnet en gammel udgave af projektet :) Lige et øjeblik.
Synes godt om
Slettet bruger
01. december 2008 - 10:24#99
Beklager, men det lader til, at der er et problem med din Pow-metode... Prøv at køre følgende kode:
--- Chudnovsky.cs ---
using System; using System.Collections.Generic; using System.Linq; using System.Text;
using Microsoft.FSharp.Math;
namespace FChudnovskyTest { public class Chudnovsky { public BigInteger Precision = 0; public BigNum Result = BigNum.FromInt(0); public long Time = 0;
public Chudnovsky() { } public Chudnovsky(BigInteger n) { Calculate(n); }
public BigNum Calculate() { return Calculate(Precision); } public BigNum Calculate(BigInteger n) { long time = Environment.TickCount; // Get current ticks Precision = n; // Update precision variable if (n > 0) { BigNum result = BigNum.FromInt(0); for (BigInteger k = 0; k < n; k++) // Run algorithm result += ( // Let's give the processor a helping hand by first doing all the integer arithmetics new BigInteger(-1).Power(n) * (new BigInteger(6) * n).Faculty() * new BigInteger(13591409) + new BigInteger(545140134) * n / n.Faculty().Power(new BigInteger(3)) / (new BigInteger(3) * n).Faculty() ).ToBigNum() / // Now that all the integers are united as a final numerator and converted to a decimal type, let's divide by the denominator BigNumExtensions.Pow(BigNum.FromInt(640320), (new BigInteger(3) * n).ToBigNum() + BigNum.FromInt(3) / BigNum.FromInt(2), 0); Result = BigNum.FromInt(1) / BigNum.FromInt(12) / result; // Finally, let's get a clean result } else Result = BigNum.FromInt(0); // Obviously, we won't get a result if we never run the algorithm Time = Environment.TickCount - time; // Get ticks spent on conculations return Result; } } }
--- BigNumExtensions.cs ---
using System; using System.Collections.Generic; using System.Linq; using System.Text;
using Microsoft.FSharp.Math;
namespace FChudnovskyTest { public class BigNumExtensions { /* public static BigNum Power(BigNum x, BigNum y) { if (y == BigNum.FromInt(0)) return BigNum.FromInt(1); else if (y == BigNum.FromInt(1)) return x; else { BigNum z = y / BigNum.FromInt(2); return Power(x, z) * Power(x, y - z); } // This method is needed as the built-in PowN method of the BigNum class does not support decimal numbers as power arguments. } */
public static string MyToString(BigNum x, int nodec) { StringBuilder sb = new StringBuilder(); BigInt n = x.Numerator; BigInt d = x.Denominator; BigInt intpart = n / d; sb.Append(intpart.ToString()); n = n - intpart * d; sb.Append("."); for (int i = 0; i < nodec; i++) { n = n * BigInt.FromInt32(10); intpart = n / d; sb.Append(intpart.ToString()); n = n - intpart * d; } return sb.ToString(); } public static BigNum Sqrt(BigNum x, int nodec) { BigInt precision = BigInt.Parse("1".PadRight(nodec, '0')); BigNum curr = x / BigNum.Parse("10"); BigNum last; BigNum tmp; do { last = curr; curr = (last + x / last) / BigNum.Parse("2"); tmp = curr - last; if (tmp.IsNegative) tmp = -tmp; } while (tmp.Numerator * precision > tmp.Denominator); return curr; } public static BigNum Pow(BigNum x, BigNum y, int nodec) { BigInt n = y.Numerator; BigInt d = y.Denominator; if (n == BigInt.Zero) { return BigNum.One; } else if (n % d == BigInt.Zero) { if (y.ToString().Length > 9) throw new ArgumentException(y + " is too big an int"); return BigNum.PowN(x, int.Parse(y.ToString())); } else if ((BigInt.Parse("2") * n) % d == BigInt.Zero) {
return Sqrt(x, nodec) * Pow(x, y - BigNum.Parse("1/2"), nodec); } else { throw new ArgumentException(y + " is not int or int + half"); } } // I would like to thank Arne Valhøj for these methods as he wrote the initial code. // See http://www.eksperten.dk/spm/850647 (Danish) for more information. } }
--- Program.cs ---
using System; using System.Collections.Generic; using System.Linq; using System.Text;
Men det går stadig galt -- helt galt :S Tilsyneladende fungerer MyToString heller ikke... Damn it :(
Synes godt om
Slettet bruger
01. december 2008 - 20:31#101
For pokker! Jeg har ingen anelse om, hvordan jeg skal få det til at fungere... Og jeg har knap nok til til at sætte mig ind i detaljerne omkring din kode. Nogen løsningsforslag?
Synes godt om
Slettet bruger
01. december 2008 - 20:45#102
Hm, hvad med http://mathnet.opensourcedotnet.info/ ? Kan det måske bruges? Jeg kan ikke rigtig gennemskue det... Der er godt nok mange funktioner i projektet.
Fuck, hvor er det frustrerende. Jeg ville ønske, der fandtes en samling matematikklasser til C#, hvor der ikke manglede alverdens elementære metoder (pow/roots, to-decimal-string, ...) :(
Synes godt om
Slettet bruger
04. december 2008 - 15:34#107
Projektet slutter i morgen... Så bare lad det ligge. Jeg må klare mig med 14 decimaler (øv!).
Jo. Men C# er tilsyneladende efter både Java og C/C++ på dette område.
Jeg hentede BigInteger klassen fra det link (det var mig der gav linket 50 indlæg oppe). Men koden compilede stadig ikke (mangler Power).
Synes godt om
Slettet bruger
23. februar 2009 - 11:00#109
Sådan. Jeg fik for nyligt projektet tilbage, og da jeg ledte efter et gammelt spørgsmål på Eksperten, stødte jeg på denne tråd. Tilsyneladende kommer man langt med at bortforklare og snakke udenom, for jeg fik topkarakter for arbejdet :) Tak for hjælpen - og ved indlæg 109 tror jeg godt, vi kan kalde emnet gennemarbejdet.
Synes godt om
Ny brugerNybegynder
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.