C# Math.Pow(-2,1.1) > n.def - c#

I just found out that when entering a negative x and a decimal y, Math.Pow() returns the not-defined value as result, which is wrong I guess. Calculating this in other programs, even like the windows Calculator works with a correct result. Also this case is not mentioned in the documentation.
Target Framework is 4.
Can anyone explain this?

The result is going to be complex number, so you have to use Complex class from System.Numerics namespace.
Complex n = new Complex(-2, 0);
Complex result = Complex.Pow(n, 1.1);
In case if result is real number (integer power), then you can use Math.Pow.
As #JeppeStigNielsen mentioned, the conversion from int/double to Complex is implicit, so the code can be shortened to:
Complex result = Complex.Pow(-2, 1.1);

Also this case is not mentioned in the documentation
You sure? From it's documentation;
Parameters
x < 0 but not NegativeInfinity; y is not an integer,
NegativeInfinity, or PositiveInfinity.
Return value
NaN
I'm not sure which OS you tried but it doesn't work in calc.exe (Win7 - 64bit) says Invalid Input.
As Ulugbek mentioned, taking 1.1 power of a negative value creates a complex number. Because (-2)1.1 = (-2)11/10 = (-2)1/1011 and getting 10 times rooth of -2 returns a complex number.
Since Math.Pow takes and returns double values, this doesn't fit with requirements. You can use Complex class from System.Numerics.
http://www.wolframalpha.com/input/?i=-2^1.1
Further reading: How is Math.Pow() implemented in .NET Framework?

Related

Trouble raising -1 to a rational fraction-based power

On my TI-84 Plus (Silver Edition), I can enter the following without error: (-1)^(1/3) = -1
I also know that entering some expressions like the following would yield a non-real -imaginary- number like: (-1)^.5
Now, my problem is with C#'s Math object. If I send any fractions like these: {1.667, 109.667, 0.667, 120.667} OR {4/3, 111/3, 2/3, 122/3}, I would get: {NaN, NaN, NaN, NaN}.
Do I have to write a new object MathHelper that checks the rational value and returns an answer according to a limited input switch? Or is there a feature to the Math object I am missing. I can do this on the calculator...
PS, I did not come across any similar questions online yet; so if this is a duplicate, please inform me ;)
[My new views]
Thank you all for your help! I had finished upgrading the "Microsoft.Solver.Foundation.dll" to the 4.0 targeted framework and it turned out that the 'Rational' object seemed to return only -1's and 'Indeterminate'. Then after entering (-1)^(1/2) [nonreal ans] on Google, it dawned on me that I was working with nth-roots!! So, it turned out that I had already managed imaginary numbers in the past in C#, hence having solved my problem:
Any even root 2n of a negative number -m will always equal an imaginary number i. (2n√-m)=i
I can't believe I forgot this simple algebra property
You will have to write your own Math helper to do functions like this (at least for Math.Pow). EDIT: Or you can use the Rational library like mentioned in the comments.
According to the documentation:
Input: x < 0 but not NegativeInfinity; y is not an integer, NegativeInfinity, or PositiveInfinity.
Result: NaN
Review the docs here: http://msdn.microsoft.com/en-us/library/system.math.pow.aspx
In C#, (-1)^R isn't defined for non-integer values of R.
If you try to calculate (-1)^(1/3), C# will calculate 1/3 first, resulting in a non-integer floating point number for R.
Solution:
Use the mathematical identity:
a^(x/y) = a^x * a^(1/y) x,y integers
For negative a, use:
a^1/y = -(|a|^1/y) // only works if y is odd
Or put together:
if (a < 0) {
if (y % 2 = 1) {
result = a^x * -1 * (-a)^(1.0/y); // Replace ^ with the correct C# call.
} else {
// NaN
}
} else {
result = a^(x/y);
}

Is there a Math API for Pow(decimal, decimal)

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

C# - How To Convert/Display a Floating-Point/Exponential Result into a Full/Whole Number

I am using C# inside .Net Environment. I have some really large integer values entered by user which are than divided by each other and the result is displayed. Now we know that 4/2 = 2 is simple but what if we divide
.0232321312321312312312312321032132139813912839013809123801283012983901283012380129382190381209382190382190382109382109382109312/ 1200000232323213213213213878978398494849023834902348239048239048239048239048239048239048239048239048239048239048239048239048239048239048239048239048239048234902384902384902384902348239048239048234
The answer is like 1.93601056119411E-197
I want to display the answer as a full decimal/floating point value instead of relying on E symbol.
I wrote some code
using System.Numerics;
BigInteger x = BigInteger.Parse("0232321312321312312312312321032132139813912839013809123801283012983901283012380129382190381209382190382190382109382109382109312");
BigInteger y = BigInteger.Parse("1200000232323213213213213878978398494849023834902348239048239048239048239048239048239048239048239048239048239048239048239048239048239048239048239048239048234902384902384902384902348239048239048234
")
BigInteger answer = BigInteger.Divide(x, y)
return answer.ToString("D")
I think that is what you are looking for, if you want the fractional part of the answer you'll have to do it all with the Complex type. Its not clear what you are doing from the question.
EDIT:
How about this
using System.Numerics;
BigInteger x = BigInteger.Parse("0232321312321312312312312321032132139813912839013809123801283012983901283012380129382190381209382190382190382109382109382109312");
BigInteger y = BigInteger.Parse("1200000232323213213213213878978398494849023834902348239048239048239048239048239048239048239048239048239048239048239048239048239048239048239048239048239048234902384902384902384902348239048239048234
")
Complex answer = Complex.Divide((Complex)x, (Complex)y)
return answer.ToString("F50") //If 50 decimal places is enough.
I assume that you not only want to preceed your value with "0.00..." but also want to see the "missing" digits after 411.
If that is the case, then you cannot do this with floating point data types, since the floating point data types in .NET simply do not have the required precision. You will need to resort to external libraries, such as, for example, W3b.Sine (untested, just found it through a quick Google search), which allow for arbitrary-precision decimals.
I use .ToString("N0") that seems to do the job when I have the same problem.

Am I going crazy or is Math.Pow broken?

I used the base converter from here and changed it to work with ulong values, but when converting large numbers, specifically numbers higher than 16677181699666568 it was returning incorrect values. I started looking into this and discovered that Math.Pow(3, 34) returns the value 16677181699666568, when actually 3^34 is 16677181699666569. This therefore throws a spanner in the works for me. I assume this is just an issue with double precision within the Pow method? Is my easiest fix just to create my own Pow that takes ulong values?
If so, what's the quickest way to do Pow? I assume there's something faster than a for loop with multiplication each time.
You can use BigInteger.Pow. Or use my power method for long.
The problem is that Math.Pow returns a double, and the closest double value to 16677181699666569 is 16677181699666568.
So without getting Math.Pow involved:
long accurate = 16677181699666569;
double closestDouble = accurate;
// See http://pobox.com/~skeet/csharp/DoubleConverter.cs
Console.WriteLine(DoubleConverter.ToExactString(closestDouble));
That prints 16677181699666568.
In other words whatever Math.Pow does internally, it can't return a result that's more accurate than the one you're getting.
As others have said, BigInteger.Pow is your friend if you're using .NET 4.
Read What Every Computer Scientist Should Know About Floating-Point
Floating point types are an approximation, the rounding you see is normal.
If you want exact results use BigInteger.
I assume this is just an issue with
double precision within the Pow
method?
Yes.
Is my easiest fix just to create my
own Pow that takes ulong values?
You can use BigInteger.Pow.
If you're using .NET Framework 4, Microsoft has included a new BigInteger class that lets you manipulate large numbers.
http://msdn.microsoft.com/en-us/library/system.numerics.biginteger.aspx
Alternatively, you can use a nice library that someone else created:
http://intx.codeplex.com/ (IntX library)

Why doesn't Math.Round/Floor/Ceiling return long or int?

Every time I use Math.Round/Floor/Ceiling I always cast to int (or perhaps long if necessary). Why exactly do they return double if it's always returning an integer.
The result might not fit into an int (or a long). The range of a double is much greater.
Approximate range of double: ±5.0 × 10−324 to ±1.7 × 10308
(Source)
I agree with Mark's answer that the result might not fit in a long, but you might wonder: what if C# had a much longer long type? Well, here's what happens in Python with it's arbitary-length integers:
>>> round(1.23e45)
1229999999999999973814869011019624571608236032
Most of the digits are "noise" from the floating-point rounding error. Perhaps part of the motivation for Round/Floor/Ceiling returning double in C# was to avoid the illusion of false precision.
An alternative explanation is that the .NET Math module uses code written in C, in which floor and ceil return floating-point types.
Range arguments aside, none of these answers addresses what, to me, is a fundamental problem with returning a floating point number when you really want an exact integer. It seems to me that the calculated floating point number could be less than or greater than the desired integer by a small round off error, so the cast operation could create an off by one error. I would think that, instead of casting, you need to apply an integer (not double) round-nearest function to the double result of floor(). Or else write your own code. The C library versions of floor() and ceil() are very slow anyway.
Is this true, or am I missing something? There is something about an exact representation of integers in an IEEE floating point standard, but I am not sure whether or not this makes the cast safe.
I would rather have range checking in the function (if it is needed to avoid overflow) and return a long. For my own private code, I can skip the range checking. I have been doing this:
long int_floor(double x)
{
double remainder;
long truncate;
truncate = (long) x; // rounds down if + x, up if negative x
remainder = x - truncate; // normally + for + x, - for - x
//....Adjust down (toward -infinity) for negative x, negative remainder
if (remainder < 0 && x < 0)
return truncate - 1;
else
return truncate;
}
Counterparts exist for ceil() and round() with different considerations for negative and positive numbers.
There is no reason given on the docs that I could find. My best guess is that if you are working with doubles, chances are you would want any operations on doubles to return a double. Rounding it to cast to an int was deemed by the language designer less common then rounding and keeping as a double.
You could write your own method that cast it to an int for you in about 2 lines of code, and much less work than posting a question on stack overflow...

Categories

Resources