我注意到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 $,请参见下图
与它的外观相反
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;
}
其他问题 像大多数现代制图程序(如上所述)一样,表示/标绘函数的数据是否准确?或者考虑到常规幂函数将负底数或指数的额外数据视为未定义,这是否确实具有误导性?这些区域或图中的某些部分在数学上是什么称呼(这是技术术语)?
也可以接受其他任何方法或算法