比我更好的程序员。这不是什么大不了的事,但我对这个功能感到好奇,更重要的是它有时给出的结果。所以我为家庭作业定义了一个递归幂函数,包括负指数。对于正值和0,它工作正常,但是当我输入一些负值时,答案真的很奇怪。这是功能:
public static double Power(int base, int exp){
if (exp == 0)
return 1.0;
else if(exp >=1)
return base * Power(base, exp - 1);
else
return (1.0/base) * Power(base, exp + 1);
}
因此,对于调用Power(5,-1),函数返回0.2,就像它应该的那样。但是对于说Power(5,-2),该函数返回0.04000000000000001而不是0.04。 同样,这不是一个大问题,因为它是为家庭作业而不是“现实生活”,但只是好奇为什么会发生这种情况。我认为它与计算机内存或双值存储有关,但实际上并不知道。谢谢大家!
PS,如果有所不同,可以使用Netbeans在Java中编码。
答案 0 :(得分:0)
通过仔细组织算术可以减少浮点舍入误差。通常,您希望最小化舍入操作的数量,以及对舍入结果执行的计算次数。
我对你的功能做了一些小改动:
public static double Power(int base, int exp) {
if (exp == 0)
return 1.0;
else if (exp >= 1)
return base * Power(base, exp - 1);
else
return (1.0 / Power(base, -exp));
}
对于您的测试用例Power(5, -2)
,这只会进行一次舍入计算,即递归顶部的除法。它得到最接近的1 / 25.0倍,打印为0.04。
答案 1 :(得分:0)
这可能是一个被忽视或有争议的答案,但我认为需要说明。
其他人则关注“浮点”计算(例如涉及一个或多个“双打”数字的计算)近似数学的信息。
我对这个答案的关注点在于,即使普通Java代码中的这种方式,以及大多数编程语言中的普通代码,使用0.1
等数字的计算也不必是近似的
一些语言将0.1
之类的数字视为有理数,两个整数之间的比率(分子超过分母,在这种情况下为1
超过10
或十分之一)就像它们一样在学校数学。只涉及整数和有理数的计算是100%准确的(忽略整数溢出和/或OOM)。
不幸的是,如果分母变得过大,理性计算会在病理上变慢。
有些语言采取妥协的立场。他们将一些理性视为有理数(因此具有100%的准确性),只有在理性计算在病理上缓慢时,才会放弃100%的准确性,转换为浮点数。
例如,这里有一些相对较新且具有前瞻性的编程语言的代码:
sub Power(\base, \exp) {
given exp {
when 0 { 1.0 }
when * >= 1 { base * Power(base, exp - 1) }
default { 1.0/base * Power(base, exp + 1) }
}
}
这会以其他语言复制您的代码。
现在使用此函数获取指数列表的结果:
for 1000,20,2,1,0,-1,-2,-20,-1000 -> \exp { say Power 5, exp }
Running this code in glot.io显示:
9332636185032188789900895447238171696170914463717080246217143397959
6691097577563445444032709788110235959498993032424262421548752135403
2394841520817203930756234410666138325150273995075985901831511100490
7962651131182405125147959337908051782711254151038106983788544264811
1946981422866095922201766291044279845616944888714746652800632836845
2647429261829862165202793195289493607117850663668741065439805530718
1363205998448260419541012132296298695021945146099042146086683612447
9295203482686461765792691604742006593638904173789582211836507804555
6628444273925387517127854796781556346403714877681766899855392069265
4394240087119736747017498626266907472967625358039293762338339810469
27874558605253696441650390625
95367431640625
25
5
1
0.2
0.04
0.000000000000010
0
以上结果100%准确 - 直到最后一个指数-1000
。如果我们检查结果的类型(使用WHAT
),我们可以看到语言放弃了100%的准确度:
for 1000,20,2,1,0,-1,-2,-20,-1000 -> \exp { say WHAT Power 5, exp }
显示:
(Rat)
(Rat)
(Rat)
(Rat)
(Rat)
(Rat)
(Rat)
(Rat)
(Num)
将Rat
s(默认的理性类型)转换为FatRat
s(任意精确的有理类型),即使使用病态较大的分母,也可以避免不准确:
sub Power(\base, \exp) {
given exp {
when 0 { 1.0.FatRat }
when * >= 1 { base * Power(base, exp - 1) }
default { 1.0.FatRat/base * Power(base, exp + 1) }
}
}
这产生与原始代码相同的显示,除了最后的计算结果:
0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
我不知道这是否准确,但是,aiui,它应该是。