分数指数和负数基的数学修改的pow函数

时间:2019-06-15 01:54:27

标签: java math plot numerical-methods pow

我注意到Desmos或Geogebra或Google(谷歌搜索x ^(1/3))之类的计算器和制图程序必须修改了Math.pow()函数的版本,该函数允许它们绘制一些负基和分数使用常规Math.pow()函数无法定义的指数。

我正在尝试重新创建此修改的pow函数,以便可以绘制图形的缺失部分,例如$ x ^ {\ frac {1} {3}} $,其中$ x <0 $

我的尝试

我不知道此修改后的pow函数在计算机科学或数学文献中被称为什么,因此我无法查找有助于创建该函数的健壮和优化版本的参考。相反,我尝试在Apache math3库的Fraction类的帮助下制作自己的版本,以确定一些条件语句,例如分数指数的分子和分母是偶数还是奇数。

我的版本中有几个问题要概述,可能会遗漏一些我尚未考虑的可能导致错误的额外条件。

    /* Main Method */
    public static void main(String[] args) {
        double xmin = -3;
        double xmax = 3;
        double epsilon = 0.011;

        /* print out x,y coordinates for plot */
        for (double x = xmin; x <= xmax; x += epsilon){
            System.out.println(x+","+f(x));
        }
    }

    /* Modified Power Function*/
    private static double pow2(double base, double exponent){
        boolean negativeBase = base < 0;

        /* exponent is an integer and base non-negative */
        if (exponent == ((int) exponent) && !negativeBase){
            /* use regular pow function */
            return Math.pow(base, exponent);
        }

        Fraction fraction;
        try {
            fraction = new Fraction(exponent, 1000); /* maxDenominator of 1000 for speed */
        } catch (FractionConversionException e){
            return Double.NaN;
        }

        /* updated: irrational exponent */
        if (exponent != fraction.doubleValue()){
            /* handles irrational exponents like π which cannot be reduced to fractions.
             * depends heavily on the maxDenominator value set above.
             * With a maxDenominator of 1000, fractions like 1/33333 who's denominator has greater then 4 digits
             * will be considered as irrational. To avoid this, increase maxDenominator to 10000 but will slow down performance.
             * That's the trade off with this part of the algorithm.
             * Also this condition helps clear up a lot the mess on a plot.
             * If the plot is centered at exactly origin (0,0) the messy artifacts may appear, but by offsetting
             * the view of the plot slightly from the origin will make it disappear
             * or maybe it has more to do with the stepsize epsilon (0.01 (clean number) vs 0.011 (irregular number))
             * */
            return Math.pow(base, exponent);
        }

        if (fraction.getDenominator() % 2 == 0){
            /* if even denominator */
            if (negativeBase){
                return Double.NaN;
            }
        } else {
            /* if odd denominator, allows for negative bases */

            if (negativeBase){
                if (fraction.getNumerator() % 2 == 0){
                    /* if even numerator
                     * (-base)^(2/3) is the same as ((-base)^2)^(1/3)
                     * any negative base squared is positive */
                    return Math.pow(-base, exponent);
                }

                /* return negative answer, make base and exponent positive */
                return -Math.pow(-base, exponent);
            }
        }

        return Math.pow(base, exponent);
    }

    /* Math function */
    private static double f(double x){
        /* example f(x) = x^(1/x) */
        return pow2(x, (double) 1/x);
    }

问题#1

对于这两个问题,我将使用数学函数$ f(x)= x ^ {\ frac {1} {x}} $作为演示这两个问题的图的示例-第一个是FractionConversionException这是因为指数值较大。如果我的代码中的epsilon值更改为0.1,将会发生此错误,但是当步进大小epsilon为0.11时,似乎可以避免该错误。我不确定如何正确解决它,但是在Fraction类中,它抛出了FractionConversionException,它使用条件语句,可以将其复制到我的pow2()函数中,并使用下面的代码返回NaN。但是我不确定这是否正确!

        long overflow = Integer.MAX_VALUE;

        if (FastMath.abs(exponent) > overflow) {
            return Double.NaN;
        }

编辑:在Fraction类的实例周围添加try / catch语句,并在catch子句中返回NaN似乎是一个不错的解决方法。而不是上面的代码。

问题2

绘制数学函数$ f(x)= x ^ {\ frac {1} {x}} $会在左侧产生一个混乱的区域,其中$ x <0 $,请参见下图

x^(1/x) plot

与它的外观相反

https://www.google.com/search?q=x^(1%2Fx)

我不怎么摆脱这种混乱,因此在$ x <0 $的地方应该是未定义的(NaN),同时允许pow2()函数仍然绘制$ x ^ {\ frac { 1} {3}} $,$ x ^ {\ frac {2} {3}} $,$ x ^ {x} $等...

我也不确定在实例化Fraction对象时如何设置maxDenominator以获得良好的性能,同时又不影响绘图结果。也许有一个更快的十进制到分数转换算法,尽管我认为Apache math3可能已经非常优化。

编辑: 问题3 我忘记考虑不合理的指数,因为我太精打细算了。我的算法对像π这样的非理性指数失败,并将两个版本的图绘制在一起。由于分数类对指数取整的方式,某些分母被视为偶数和奇数。可能有一个条件,如果无理指数不等于分数,则返回NaN。刚刚快速测试了此条件,就不得不添加一个negativeBase条件,以正确的方式翻转图形。需要做进一步的测试,但这可能是个主意。

Edit2:经过测试后,它实际上应该返回常规的pow()函数而不是NaN来处理非理性指数的条件(请参见有关修改的幂函数的更新代码),并且这种方法出人意料地设法摆脱了大多数问题2中突出显示的混乱,因为我认为区间中的无理数要比有理数多,该算法对该数进行了折衷处理,从而使其密度降低了,并且很难将两个点连接成一条线以显示在图中。


        if (exponent != fraction.doubleValue() && negativeBase){
            return Double.NaN;
        }

其他问题 像大多数现代制图程序(如上所述)一样,表示/标绘函数的数据是否准确?或者考虑到常规幂函数将负底数或指数的额外数据视为未定义,这是否确实具有误导性?这些区域或图中的某些部分在数学上是什么称呼(这是技术术语)?

也可以接受其他任何方法或算法

0 个答案:

没有答案