C#Math.Pow()是破(C# Math.Pow() is broken)

2019-07-18 07:42发布

不,这不会(我的理解)涉及整数除法或浮点四舍五入问题。

我确切的代码是:

    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客户端配置文件。

奇怪的是我还没有发现在网络上任何地方这个任何提及。 我是服用药片的疯狂这里!?

Answer 1:

似乎指定为恰好; 从所述Math.Pow()备注部上Pow(x,y) ;

参数
X <0但不NegativeInfinity; y为不是整数,NegativeInfinity,或PositiveInfinity时。

结果
为NaN



Answer 2:

勒夫的回答解释说,战俘根据其规范行为。

为什么是()指定的方式战俘? 因为1.0/7.0不等于1/7。 你问的0.14285714285714285功率的-128.0 ,并没有与该物业没有实数,所以结果是正确的NaN。 对于所有的奇数n != 11.0/(double)n是不准确地表示,这样可以不通过使用计算x的n次方根pow(x, 1.0/(double)n) 因此pow(x, y)被指定为返回的NaN为负x和非整数ý -存在用于任何的这些情况下,没有适当的真实结果。



Answer 3:

这里的问题是“第七根”的数学定义是一个多值函数 。 虽然这是事实,

(-2)= 7 -128

并不意味着-2是(-128)1/7的唯一答案。 在复平面中,第七根功能是多值的并有许多可能的答案(正如4的平方根可被认为是+2或-2,但2是通常的回答)。

为了简化这样的表达式的数学处理中, 主值是按照惯例用于所讨论的功能选择,使得功能变得单值。 在第七根的情况下,主要的值,通过给定的钨阿尔法为(-128)1/7

所述Math.Pow()在C#函数尝试用于返回主值pow功能。 当结果的主值将是一个复杂的数,则返回NaN



Answer 4:

负实数的分数幂是一个复杂的数(见数学论坛的详细解释)。



Answer 5:

我固定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;
    }
}


Answer 6:

!为1.0 / 3 = 1/3,我使用Rational可以在Microsoft.SolverFoundation.Common。见准确表示1/3: https://msdn.microsoft.com/en-us/library/microsoft.solverfoundation.common .rational%28V = vs.93%29.aspx?F = 255&MSPPError = -2147217396

我能赶上奇根的链接1/3,因为我可以得到分母。

如果我得到一个根是斧子,我使用的代码获得的分子和分母。

            var at = (double)ax.Numerator;
            var down = (double)ax.Denominator;

理性可以使2/6 =三分之一。

但Rational.Pow不能计算出百百凹心不是积极的。

我觉得百百凹心不是积极的,而分母是偶数和分子为奇。

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

如果分子为偶数,分子的POW使百百凹是积极的。

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


文章来源: C# Math.Pow() is broken