54

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.

Grant Thomas
  • 44,454
  • 10
  • 85
  • 129
Maxime ARNSTAMM
  • 5,274
  • 10
  • 53
  • 76
  • why can't you use doubles? Try using ILSpy or Reflector and getting the code from Math.Pow and modifying it to use decimal as you need. – Dustin Davis Jun 21 '11 at 12:52
  • There's some strange requirements. What's stopping you writing one? – spender Jun 21 '11 at 12:53
  • At the end of the day I think you will have to use series if you want higher precision than doubles, they would be as precise as you decide, just depends how many terms you want to evaluate. – James Gaunt Jun 21 '11 at 12:54
  • @Dustin: He wants `decimal`, not `float` or `double`. I would imagine that he cannot use floating point types of any kind. – Adam Robinson Jun 21 '11 at 12:54
  • How much precision do you need? – recursive Jun 21 '11 at 12:54
  • 3
    This might help: [Raising a decimal to a power of decimal ?](http://stackoverflow.com/questions/429165/raising-a-decimal-to-a-power-of-decimal) – Paolo Moretti Jun 21 '11 at 12:56
  • it's from a formula where money is involved. If i risk loosing precision while multipliying everything, i'm afraid the results won't be good looking. – Maxime ARNSTAMM Jun 21 '11 at 13:16
  • 1
    One of the multipliyers is a rate : 1 / someOtherDecimalRate^(nbDays/365). – Maxime ARNSTAMM Jun 21 '11 at 13:22
  • 3
    @Maxime: You are going to lose precision there. Decimals are made for decimal numbers, and fractions of 365 are not exactly representable in base 10, so the result of `nbDays/365` is already inexact. – etarion Jun 21 '11 at 13:50
  • To my mind the problem is not so much the loss of precision but the possibility of "conversion inconsistency" when converting from decimal to double. See [Conversion of a decimal to double number in C# results in a difference](http://stackoverflow.com/a/23638323/609428) – Ilan May 13 '14 at 18:12
  • Also see [Raising a decimal to a power of decimal?](http://stackoverflow.com/a/23855790/609428) for a manual implementation of Math.Pow(decimal,decimal) – Ilan May 25 '14 at 13:35

6 Answers6

52

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.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • Doesn't `decimal` provide more precision? The 64 extra bits it gets have to help a little... – configurator Jun 22 '11 at 12:24
  • 4
    @configurator: The answer to your question is "yes". Your statement following the question does not follow logically from the answer to the question. Why does having twice the number of bits help in a financial problem that only has to be accurate to, say, the tenth of a penny? Clearly the question is about a compounded-daily interest calculation; are there compounded-daily banking problems that require more than 15 decimal digits of precision when working out today's interest? If today's interest is $10.92857924858 in double and $10.9285792485820968039468095 in decimal, does it matter? – Eric Lippert Jun 22 '11 at 14:11
  • 3
    When I worked on compound daily interests we were required to be accurate to within 12 decimal digits, which I personally feel is dangerously close to `double`'s limits. (Never mind that the 12 digits were completely arbitrary and 'accurate' meant 'same value as the seriously flawed old VB3 implementation' so we needed to introduce calculation errors...) – configurator Jun 22 '11 at 14:47
  • @configurator: Wow, that sounds like fun. I am not an expert in numerical methods by any means, but I did a reasonable amount of both study and some professional work early in my career, and it's been my experience that unless there is some "stiffness" in the partial differential equation you're solving, accuracy to twelve places is unnecessary. Was there some numerical-methods-based justification for the twelve-figure requirement? – Eric Lippert Jun 22 '11 at 15:04
  • @Eric: They were pension calculations done on a daily basis for 40-50 years in the typical case, so any slightest error can combine quite easily. Add to that that the final results were aggregated (wrongly!) across companies to sum their total pension funds, and you need accuracy far beyong 3 decimal points... – configurator Jun 23 '11 at 16:21
  • 1
    So I had found myself in a situation whereas my precision demanded close to 32 numbers before the dot. I had found that the usage of decimals with 28 numbers before the dot and 28 after, made that possible. In my case, I altered the whole set of equations to fit inside those 56 numbers. Well, my point is, sometimes we really need more than just the framework can achieve by itself, and for that we have go a little further than we'd expect. Use log, cos, sin. Probably someone might had bumped into your situation and have a mathematic solution to it. Good luck – marcelo-ferraz Jan 20 '14 at 12:49
  • 1
    "Who cares if it's off by a few billionths, you'll round out the error later" - Sometimes it does matter. e.g. if you get a value of 2.4999999998 when you were expecting 2.5 and want to round it to the nearest integer, now you're getting 2 instead of 3, which is incorrect. – komodosp Jun 11 '15 at 13:41
  • 1
    @colmde: Exactly my point. By rounding you are saying that you are willing to take on an error many, many orders of magnitude larger than the error induced by the computation process. If a *large* rounding introduces too much error after a *small* error is introduced then you should not be doing the large rounding in the first place. – Eric Lippert Jun 11 '15 at 20:04
  • @EricLippert, what do you mean by short decimal? – Juan M. Elosegui Aug 13 '15 at 01:42
  • @jmelosegui: It was not clear what I meant. What I meant was that if you want to represent 123 dollars and 45 cents then use decimal; the pennies are exact. Computations that produce values involving significant digits to the millionth or a billionth of a cent are unlikely to be meaningful in the dollars-and-cents domain. – Eric Lippert Aug 19 '15 at 13:15
  • The shifting operator (<<) analogue is somewhat relevant though, and that's a special case of the power operator. – John Apr 21 '17 at 09:30
  • While the answer is true in this case, I can think of use cases where having `Math.Pow(decimal, decimal)` seems rather necessary to me. For example I have to validate that a value will fit inside a `decimal(p,s)` field in the database. The simplest way to do that is to use `10^(p-s)` as the upper bound. Trying to do that with doubles will not work in all cases (it's not that trivial to figure out what the first power is for which this fails) – Voo Mar 27 '19 at 16:27
  • 1
    @EricLippert It's used in the calculation of geometric mean, which _is_ used in finance, such as the FT30 index or the RPIJ inflation index. There absolutely is reason to use this with Decimal. Claiming there isn't any reason is irresponsible. "I'm not aware of any" is a much more honest position. – Patrick Kelly Jan 24 '21 at 18:57
  • Part of the question wasn't necessarily how to calculate a power, but why there is no API. Just the silly casting when you are working with decimals and have to use a certain mathematical function is already cumbersome. And it's not like you can't do a power function on decimal either. Whether the precision is relevant or if a double would be more fitting should be left to the programmer. For example, I need Pow just to truncate to a variable number of decimals, where the lack of API shows again. Fortunately I can completely forego Math.Pow and use the operator on int. – Alexander Gräf Aug 21 '22 at 20:05
  • actually power(10,-6) is exactly represented by decimal value – Fantastory Jun 05 '23 at 12:16
9

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.

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
Andrew
  • 115
  • 1
  • 3
  • 8
    Yes I did that till the result was outside of the range of decimal and I ended up with an overflow exception – Bob Vale Mar 01 '18 at 13:55
7

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).

Andre
  • 326
  • 4
  • 12
2

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.

James Gaunt
  • 14,631
  • 2
  • 39
  • 57
  • The OP later mentioned that he is using `Decimals` because he is working with money. In that situation, I think he's better off following [Eric Lippert's advice](http://stackoverflow.com/questions/6425501/is-there-a-math-api-for-powdecimal-decimal/6426826#6426826). – Brian Jun 21 '11 at 15:50
  • Fair enough - that fact he was doing financial calculations was added at a later point. Obviously there is no need for the kind of accuracy he's talking about with financial calculations. – James Gaunt Jun 21 '11 at 18:18
  • This isn't true. Pow is used in the calculation of things like the geometric mean, which is used to calculate the FT30 index, FPIJ inflation index, and more. It's much more honest to say "I'm not aware of any case" than to claim it isn't used at all. – Patrick Kelly Jan 24 '21 at 19:02
  • 1
    Wow - 9 years ago - blast from the past. Just re-reading the post and I can't see anywhere I claim "it isn't used at all". I just say there isn't much call for it - which is true. But thanks for the comment. – James Gaunt Jan 26 '21 at 09:17
  • That’s strange. I’ve been in financial software for decades on two different continents and it’s used extensively in the applications I have worked on. Financial projections, compound interest, present value of annuities, etc. Obviously, there are different kinds of financial software. – Late Starter Nov 16 '22 at 20:13
-1

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?

Jeson Martajaya
  • 6,996
  • 7
  • 54
  • 56
-12

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);
Joel Martinez
  • 46,929
  • 26
  • 130
  • 185