I'm using System.Numerics.BigInteger in .Net 4.0 and BigRational class from BCL to build a math parser/calculator application. The goal is to write a fully functional math parser with support for big numbers ... So I need to use math functions. But unfortunately all System.Math functions return typical data types like float and double so are not very accurate. I need more precision. I dug into microlib.dll but for sine function, just found this:
[SecuritySafeCritical, __DynamicallyInvokable]
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern double Sin(double a);
I know that many math function are not implemented in .Net and come directly from hardware codes. So can I use those function and get high precision or big integers? If not, what's the best way to implement them myself? (performance is also important) Any resources or pointing to the right direction would be appreciated!
I wrote a high precision float class (HPF) in MATLAB. And, yes, it IS practical to do the computations asked about here in thousands of digits, at least within limits. Don't expect the result to be lightning fast for numbers that massive.
Here, in well under a second of CPU time, compute sin(0.5) to 2000 decimal digits using HPF.
x = hpf('0.5',2000);
z = sin(x)
z =
0.47942553860420300027328793521557138808180336794060067518861661312553500028781483220963127468434826908613209108450571741781109374860994028278015396204619192460995729393228140053354633818805522859567013569985423363912107172077738015297987137716951517618072114969807370147476869703198703900097339549102989443417733111109673903936124163653480401918346314376284392645260157071283092766006791017533631162287616795734840371866817730333179872034064567347182994506824663612455463453278289361244779536601735462820464717823776898881644512826197840291735466150683689733147287397488788190207928799138423095503817584705030067646428267136203352514539875309014204847017729272889212301417866971280026511717607919387379654420848964303389447566823572876762597714624447000807836928214941991138743810551646471072080462812247422335610868323144633547779337371136437454965479015122728507221582125562761335681781172799521300086891593889552064797344909502979313524137777091507360571026506015248874581726210924892801291055435819896189522803930563792190652684778508854934451273978032859742747386701227727154948654357881637851140514356687525131655792391290065314050467763961605300872097475383191474571466991222453822643126018869834327176291251787779457463370925032134676572752244926564204875494171901976363708322142014379355418299630547673437168013019784069157658698329043158470653971407921567047204742130833307984199944961246141304498844116424471800555566374594078227611966253268668739369977542338090766178818446935337871719545939020589010000184922392803416567433189354514503108047619925727424426280213643488597421990337636199906535549697075412246167977122862009545754093682493517801100883291428841032100118426615836052047298714537824867973933776850058028935197623983399376280971742853670048048344682272994976197375983973258649430222855535025176957323557911906997589014243194056649766589116017811954178461482380269627190632898835306576210057831124120168311609126946042808735584921993653157751619630908157551923919459017792007414
asin(z)
ans =
0.5
asin(z) - x
ans =
3.e-2004
I wrote HPF essentially from scratch, without recourse to an existing code like the Java BigDecimal class, which I did test out. In fact, I wrote the entire class several times, once as an overlay on java.math.BigDecimal class. I found I did not like their implementation, so I started over and wrote it myself. You can find details in a .pdf file included in the zip.
Having said all that, I spent literally man-months in that effort, learning various tricks to tease many thousands of digits from a series implementation.
So even if you do use a tool like the java BigDecimal class, you will still probably need to find or build tools to compute special functions on those numbers. This was the part that cost most of my time.
Are such computations, done in thousands of digits, a good use of CPU time? Only you know. Personally, it was a great deal of fun to write a tool like that.
You will need to implement them yourself. For trig functions, you will want to read up on Taylor series.
However, I doubt this will be practical for thousands of digits. Do you really need that much precision? Generally, if precision like this is really required, you're probably better off not evaluating functions, especially transcendental functions, and working with them symbolically instead.
At the very least, you'll need an arbitrary precision floating point numbers. You could use BigIntegers for this (one for exponent, one for the mantissa). Rational numbers won't be practical.
Related
I need to be able to use the standard math functions on decimal numbers. Accuracy is very important. double is not an acceptable substitution. How can math operations be implemented with decimal numbers in C#?
edit
I am using the System.Decimal. My issue is that System.Math does not work with System.Decimal. For example, the following functions do not work with System.Decimal:
System.Math.Pow
System.Math.Log
System.Math.Sqrt
Well, Double uses floating point math which isn't what you're after unless you're doing trigonometry for 3D graphics or something.
If you need to do simple math operations like division, you should use System.Decimal.
From MSDN: The decimal keyword denotes a 128-bit data type. Compared to floating-point types, the decimal type has a greater precision and a smaller range, which makes it suitable for financial and monetary calculations.
Update: After some discussion, the problem is that you want to work with Decimals, but System.Math only takes Doubles for several key pieces of functionality. Sadly, you are working with high precision numbers, and since Decimal is 128 bit and Double is only 64, the conversion results in a loss of precision.
Apparently there are some possible plans to make most of System.Math handle Decimal, but we aren't there yet.
I googled around a bit for math libraries and compiled this list:
Mathdotnet, A mathematical open source (MIT/X11, LGPL & GPL) library written in C#/.Net, aiming to provide a self contained clean framework for symbolic algebraic and numerical / scientific computations.
Extreme Optimization Mathematics Library for .NET (paid)
DecimalMath A relative newcomer, this one advertises itself as: Portable math support for Decimal that Microsoft forgot and more. Sounds promising.
DecimalMath contains all functions in System.Math class with decimal argument analogy
Note : it is my library and also contains some examples in it
You haven't given us nearly enough information to answer the question.
decimal and double are both inaccurate. The representation error of decimals is zero when the quantity being represented is exactly equal to a fraction of the form (x/10n) for suitable choices of x and n. The representation error of doubles is zero when the quantity is exactly equal to a fraction of the form (x/2n) again for suitable choices of x and n.
If the quantities you are dealing with are not fractions of that form then you will get some representation error, period. In particular, you mention taking square roots. Many square roots are irrational numbers; they have no fractional form, so any representation format that uses fractions is going to give small errors.
Can you explain what you are doing in hugely more detail?
Background
I work in the field of financial trading and am currently optimizing a real-time C# trading application.
Through extensive profiling I have identified that the performance of System.Decimal is now a bottleneck. As a result I am currently coding up a couple of more efficient fixed scale 64-bit 'decimal' structures (one signed, one unsigned) to perform base10 arithmatic. Using a fixed scale of 9 (i.e. 9 digits after the decimal point) means the underlying 64-bit integer can be used to represent the values:
-9,223,372,036.854775808 to 9,223,372,036.854775807
and
0 to 18,446,744,073.709551615
respectively.
This makes most operations trivial (i.e. comparisons, addition, subtraction). However, for multiplication and division I am currently falling back on the implementation provided by System.Decimal. I assume the external FCallMultiply method it invokes for multiplication uses either the Karatsuba or Toom–Cook algorithm under the covers. For division, I'm not sure which particular algorithm it would use.
Question
Does anyone know if, due to the fixed scale of my decimal values, there are any faster multiplication and division algorithms I can employ which are likely to out-perform System.Decimal.
I would appreciate your thoughts...
I have done something similar, by using the Schönhage Strassen algorithm.
I cannot find any sources now, but you can try to convert this code to the C# language.
P.S. i cannot say for sure about System.Decimal, but the "Karatsuba algorithm" is used by System.Numerics.BigInteger
My take of fixed point arithmetic (in general, not knowing about about C# or .NET in particular (VS Express acting up) (then, there's Fixed point math in c#? and Why no fixed point type in C#?):
The main point is a fixed scale - and that this is conceptual, first and foremost - the hardware couldn't care less about meaning/interpretation of numbers (or much anything) (unless it supports something, if for marketing reasons)
the easy: addition/subtraction - just ignore scaling
multiplication: compute the double-wide product, divide by scale
division: multiply (widened) dividend by scale and divide
the ugly - transcendental functions beyond exponentiation (exponentiate, multiply by scale to half that power)
in choosing a scale, don't forget conversion to and from digits, which may vastly outnumber multiplication&division (and give using a square a thought, see above …)
That said, "multiples of word size" and powers of two have been popular choices for scale due to speed in multiplying and dividing by such a scale. This still may make a difference with contemporary processors, if not for main ALUs of PCs - think SIMD extensions, GPUs, embedded …
Given what little I was able to discern of your application and requirements (consider disclosing more), three generic choices to consider are 10^9 (to the 9th power), 2^30 and 2^32. The latter representations may be called 34.30 and 32.32 for the bit lengths of their integral and fractional parts, respectively.
With a language that allows to create types (especially supporting operators in addition to invokable procedures), I deem designing and implementing that new type according the principle of least surprise important.
I want my cake and to eat it. I want to beautify (round) numbers to the largest extent possible without compromising accuracy for other calculations. I'm using doubles in C# (with some string conversion manipulation too).
Here's the issue. I understand the inherent limitations in double number representation (so please don't explain that). HOWEVER, I want to round the number in some way to appear aesthetically pleasing to the end user (I am making a calculator). The problem is rounding by X significant digits works in one case, but not in the other, whilst rounding by decimal place works in the other, but not the first case.
Observe:
CASE A: Math.Sin(Math.Pi) = 0.000000000000000122460635382238
CASE B: 0.000000000000001/3 = 0.000000000000000333333333333333
For the first case, I want to round by DECIMAL PLACES. That would give me the nice neat zero I'm looking for. Rounding by Sig digits would mean I would keep the erroneous digits too.
However for the second case, I want to round by SIGNIFICANT DIGITS, as I would lose tons of accuracy if I rounded merely by decimal places.
Is there a general way I can cater to both types of calculation?
I don't thinks it's feasible to do that to the result itself and precision has nothing to do with it.
Consider this input: (1+3)/2^3 . You can "beautify" it by showing the result as sin(30) or cos(60) or 1/2 and a whole lot of other interpretations. Choosing the wrong "beautification" can mislead your user, making them think their function has something to do with sin(x).
If your calculator keeps all the initial input as variables you could keep all the operations postponed until you need the result and then make sure you simplify the result until it matches your needs. And you'll need to consider using rational numbers, e, Pi and other irrational numbers may not be as easy to deal with.
The best solution to this is to keep every bit you can get during calculations, and leave the display format up to the end user. The user should have some idea how many significant digits make sense in their situation, given both the nature of the calculations and the use of the result.
Default to a reasonable number of significant digits for a few calculations in the floating point format you are using internally - about 12 if you are using double. If the user changes the format, immediately redisplay in the new format.
The best solution is to use arbitrary-precision and/or symbolic arithmetic, although these result in much more complex code and slower speed. But since performance isn't important for a calculator (in case of a button calculator and not the one that you enter expressions to calculate) you can use them without issue
Anyway there's a good trade-off which is to use decimal floating point. You'll need to limit the input/output precision but use a higher precision for the internal representation so that you can discard values very close to zero like the sin case above. For better results you could detect some edge cases such as sine/cosine of 45 degree's multiples... and directly return the exact result.
Edit: just found a good solution but haven't had an opportunity to try.
Here’s something I bet you never think about, and for good reason: how are floating-point numbers rendered as text strings? This is a surprisingly tough problem, but it’s been regarded as essentially solved since about 1990.
Prior to Steele and White’s "How to print floating-point numbers accurately", implementations of printf and similar rendering functions did their best to render floating point numbers, but there was wide variation in how well they behaved. A number such as 1.3 might be rendered as 1.29999999, for instance, or if a number was put through a feedback loop of being written out and its written representation read back, each successive result could drift further and further away from the original.
...
In 2010, Florian Loitsch published a wonderful paper in PLDI, "Printing floating-point numbers quickly and accurately with integers", which represents the biggest step in this field in 20 years: he mostly figured out how to use machine integers to perform accurate rendering! Why do I say "mostly"? Because although Loitsch's "Grisu3" algorithm is very fast, it gives up on about 0.5% of numbers, in which case you have to fall back to Dragon4 or a derivative
Here be dragons: advances in problems you didn’t even know you had
Is there a library for decimal calculation, especially the Pow(decimal, decimal) method? I can't find any.
It can be free or commercial, either way, as long as there is one.
Note: I can't do it myself, can't use for loops, can't use Math.Pow, Math.Exp or Math.Log, because they all take doubles, and I can't use doubles. I can't use a serie because it would be as precise as doubles.
One of the multipliyers is a rate : 1/rate^(days/365).
The reason there is no decimal power function is because it would be pointless to use decimal for that calculation. Use double.
Remember, the point of decimal is to ensure that you get exact arithmetic on values that can be exactly represented as short decimal numbers. For reasonable values of rate and days, the values of any of the other subexpressions are clearly not going to be exactly represented as short decimal values. You're going to be dealing with inexact values, so use a type designed for fast calculations of slightly inexact values, like double.
The results when computed in doubles are going to be off by a few billionths of a penny one way or the other. Who cares? You'll round out the error later. Do the rate calculation in doubles. Once you have a result that needs to be turned back into a currency again, multiply the result by ten thousand, round it off to the nearest integer, convert that to a decimal, and then divide it out by ten thousand again, and you'll have a result accurate to four decimal places, which ought to be plenty for a financial calculation.
Here is what I used.
output = (decimal)Math.Pow((double)var1, (double)var2);
Now I'm just learning but this did work but I don't know if I can explain it correctly.
what I believe this does is take the input of var1 and var2 and cast them to doubles to use as the argument for the math.pow method. After that have (decimal) in front of math.pow take the value back to a decimal and place the value in the output variable.
I hope someone can correct me if my explination is wrong but all I know is that it worked for me.
I know this is an old thread but I'm putting this here in case someone finds it when searching for a solution.
If you don't want to mess around with casting and doing you own custom implementation you can install the NuGet DecimalMath.DecimalEx and use it like DecimalEx.Pow(number,power).
Well, here is the Wikipedia page that lists current C# numerics libraries. But TBH I don't think there is a lot of support for decimals
http://en.wikipedia.org/wiki/List_of_numerical_libraries
It's kind of inappropriate to use decimals for this kind of calculation in general. It's high precision yes - but it's also low range. As the MSDN docs state it's for financial/monetary calculations - where there isn't much call for POW unfortunately!
Of course you might have a specific problem domain that needs super high precision and all numbers are within 10(28) - 10(-28). But in that case you will probably just need to write your own series calculator such as the one linked to in the comments to the question.
Not using decimal. Use double instead. According to this thread, the Math.Pow(double, double) is called directly from CLR.
How is Math.Pow() implemented in .NET Framework?
Here is what .NET Framework 4 has (2 lines only)
[SecuritySafeCritical]
public static extern double Pow(double x, double y);
64-bit decimal is not native in this 32-bit CLR yet. Maybe on 64-bit Framework in the future?
wait, huh? why can't you use doubles? you could always cast if you're using ints or something:
int a = 1;
int b = 2;
int result = (int)Math.Pow(a,b);
What is the most recommended data type to use in scientific calculation in .Net? Is it float, double or something else?
Scientific values tend to be "natural" values (length, mass, time etc) where there's a natural degree of imprecision to start with - but where you may well want very, very large or very, very small numbers. For these values, double is generally a good idea. It's fast (with hardware support almost everywhere), scales up and down to huge/tiny values, and generally works fine if you're not concerned with exact decimal values.
decimal is a good type for "artificial" numbers where there's an exact value, almost always represented naturally as a decimal - the canonical example for this is currency. However, it's twice as expensive as double in terms of storage (8 bytes per value instead of 4), has a smaller range (due to a more limited exponent range) and is significantly slower due to a lack of hardware support.
I'd personally only use float if storage was an issue - it's amazing how quickly the inaccuracies can build up when you only have around 7 significant decimal places.
Ultimately, as the comment from "bears will eat you" suggests, it depends on what values you're talking about - and of course what you plan to do with them. Without any further information I suspect that double is a good starting point - but you should really make the decision based on the individual situation.
Well, of course the term “scientific calculation” is a bit vague, but in general, it’s double.
float is largely for compatibility with libraries that expect 32-bit floating-point numbers. The performance of float and double operations (like addition) is exactly the same, so new code should always use double because it has greater precision.
However, the x86 JITter will never inline functions that take or return a float, so using float in methods could actually be slower. Once again, this is for compatibility: if it were inlined, the execution engine would skip a conversion step that reduces its precision, and thus the JITter could inadvertantly change the result of some calculations if it were to inline such functions.
Finally, there’s also decimal. Use this whenever it is important to have a certain number of decimal places. The stereotypical use-case is currency operations, but of course it supports more than 2 decimal places — it’s actually an 80-bit piece of data.
If even the accuracy of 64-bit double is not enough, consider using an external library for arbitrary-precision numbers, but of course you will only need that if your specific scientific use-case specifically calls for it.
Double seems to be the most reliable data type for such operations. Even WPF uses it extensively.
Be aware that decimals are much more expensive to use than floats/doubles (in addition to what Jon Skeet and Timwi wrote).
I'd recommend double unless you need the value to be exact; decimal is for financial calculations that need this exactitude. Scientific calculations tolerate small errors because you can't exactly measure 1 meter anyways. Float only helps if storage is a problem (ie. huge matrices).