不,这不是(据我的理解)涉及整数除法或浮点舍入问题。
我的确切代码是:
static void Main(string[] args)
{
double power = (double)1.0 / (double)7.0;
double expBase = -128.0;
System.Console.WriteLine("sanity check: expected: -128 ^ 0.142857142857143 = -2. actual: " + expBase + " ^ " + power + " = " + Math.Pow(expBase, power));
System.Console.ReadLine();
}
输出结果为:
sanity check: expected: -128 ^ 0.142857142857143 = -2. actual: -128 ^ 0.14285
7142857143 = NaN
此代码的目标框架是(根据解决方案属性).NET Framework 4.0 Client Profile。
奇怪的是,我在网上的任何地方都没有提到这一点。我在这里吃疯了药吗??
答案 0 :(得分:17)
似乎完全符合规定;来自Pow(x,y)
的{{3}};
参数
x< 0但不是NegativeInfinity; y不是整数,NegativeInfinity或PositiveInfinity。结果
为NaN
答案 1 :(得分:12)
Joachim 的回答解释说,pow的行为符合其规范。
为什么指定pow()?因为1.0/7.0
不等于1/7。您要求0.14285714285714285
的{{1}}幂,并且该属性没有实数,因此结果正确为NaN。对于所有奇数-128.0
,n != 1
不能完全表示,因此您无法使用1.0/(double)n
计算x的第n个根。因此,pow(x, 1.0/(double)n)
指定为负x和非整数y返回NaN - 对于任何这些情况都没有适当的实际结果。
答案 2 :(得分:3)
这里的问题是“第七根”的数学定义是multivalued function。虽然确实如此
( - 2) 7 = -128
这 not 意味着-2是(-128) 1/7 的唯一答案。在复平面中,第七根函数是多值的并且有许多可能的答案(正如4的平方根可以被认为是+2或-2,但+2是通常的答案)。
为了简化这些表达式的数学处理,principal value按惯例选择用于所讨论的函数,以便函数变为单值。在第七根的情况下,主要值是由Wolfram Alpha for (-128)1/7给出的。
C#中的Math.Pow()
函数尝试返回pow
函数的主值。当结果的主值是一个复数时,它返回NaN
。
答案 3 :(得分:1)
负实数的分数幂是一个复数(详见[{3}})。
答案 4 :(得分:0)
我修复了Math.Pow()。
它现在有一个更大的接受域(即参数:x <0但不是NegativeInfinity; y是分子为1且奇数分母的分数),并返回新域区域的实数结果。
换句话说,(-128)^(1/7)返回-2。
注意:由于双浮点精度限制,它适用于大多数(但不是全部)小数指数。
下面是我写的Math.Pow()包装器的代码。
public class MathUtil
{
/// <summary>
/// Wrapper for Math.Pow()
/// Can handle cases like (-8)^(1/3) or (-1/64)^(1/3)
/// </summary>
public static double Pow(double expBase, double power)
{
bool sign = (expBase < 0);
if (sign && HasEvenDenominator(power))
return double.NaN; //sqrt(-1) = i
else
{
if (sign && HasOddDenominator(power))
return -1 * Math.Pow(Math.Abs(expBase), power);
else
return Math.Pow(expBase, power);
}
}
private static bool HasEvenDenominator(double input)
{
if(input == 0)
return false;
else if (input % 1 == 0)
return false;
double inverse = 1 / input;
if (inverse % 2 < double.Epsilon)
return true;
else
return false;
}
private static bool HasOddDenominator(double input)
{
if (input == 0)
return false;
else if (input % 1 == 0)
return false;
double inverse = 1 / input;
if ((inverse + 1) % 2 < double.Epsilon)
return true;
else
return false;
}
}
答案 5 :(得分:0)
对于1.0 / 3!= 1/3,我使用可以在Microsoft.SolverFoundation.Common中准确表示1/3的Rational。参见:https://msdn.microsoft.com/en-us/library/microsoft.solverfoundation.common.rational%28v=vs.93%29.aspx?f=255&MSPPError=-2147217396
我可以捕捉奇数根链接1/3因为我可以获得分母。
如果我得到一个root是ax,我使用代码得到Numerator和Denominator。
var at = (double)ax.Numerator;
var down = (double)ax.Denominator;
Rational可以使2/6 = 1/3。
但Rational.Pow无法计算powerBase不是正面的。
我发现powerBase不是正数,分母是偶数,而分子是奇数。
if (at % 2 == 1 && down % 2 == 0)
{
return Double.NaN;
}
如果分母是奇数,我使用x = x * -1
if (at % 2 == 1 && down % 2 == 1)
{
x = Math.Pow(x, (int)at);
x = x * -1;
return -1 * Math.Pow(x, 1.0 / (int)down);
}
如果分子是偶数,则分子的功率使powerBase为正。
与pow(x,2/3)类似,如果x不是正数,则在使用pow(x,2)时它将是正数
x = Math.Pow(x, (int)at);
return Math.Pow(x, 1.0 / (int)down);
您可以使用的代码
if (x < 0)
{
var at = (double)ax.Numerator;
var down = (double)ax.Denominator;
if (at % 2 == 1 && down % 2 == 0)
{
return Double.NaN;
}
if (at % 2 == 1 && down % 2 == 1)
{
x = Math.Pow(x, (int)at);
x = x * -1;
return -1 * Math.Pow(x, 1.0 / (int)down);
}
x = Math.Pow(x, (int)at);
return Math.Pow(x, 1.0 / (int)down);
}
else
{
return Math.Pow(x, a);
}