Java 为什么math.pow天生就不能处理int?(地板/天花板也一样)
我知道在Java(可能还有其他语言)中,Math.pow是在double上定义的,并返回double。我想知道,为什么编写Java的人实际上没有编写一个int-returning-pow(int,int)方法,在这位数学家看来,这个方法就像是一个新手程序员的脑门抽打(虽然很容易修复)遗漏。我忍不住想,有一些基于复杂的CS的幕后原因,我只是不知道,因为否则。。。嗯 在一个类似的主题中,ceil和floor按定义返回整数,那么它们为什么不返回整数呢Java 为什么math.pow天生就不能处理int?(地板/天花板也一样),java,pow,floor,ceil,Java,Pow,Floor,Ceil,我知道在Java(可能还有其他语言)中,Math.pow是在double上定义的,并返回double。我想知道,为什么编写Java的人实际上没有编写一个int-returning-pow(int,int)方法,在这位数学家看来,这个方法就像是一个新手程序员的脑门抽打(虽然很容易修复)遗漏。我忍不住想,有一些基于复杂的CS的幕后原因,我只是不知道,因为否则。。。嗯 在一个类似的主题中,ceil和floor按定义返回整数,那么它们为什么不返回整数呢 感谢大家帮助我理解这一点。它完全是次要的,但多年来
感谢大家帮助我理解这一点。它完全是次要的,但多年来一直困扰着我。原因在于(默认实现的JNI)的实现。CPU有一个求幂模块,该模块使用双倍作为输入和输出。既然您自己可以更好地控制它,为什么Java要为您转换它呢 对于地板和天花板,原因相同,但请注意:
(int) Math.floor(d) == (int) d; // d > 0
(int) Math.ceil(d) == -(int)(-d); // d < 0
因为
Math.pow
的结果甚至可能是NaN
或Infinity
,这取决于输入。java.lang.Math只是C数学库的一个端口
对于C语言,我认为这可以归结为CPU有专门的指令来对浮点数(而不是整数)执行Math.pow 当然,该语言仍然可以添加
int
实现。事实上,BigInteger有一个。这也是有道理的,因为pow
往往会产生相当大的数字
ceil和floor根据定义返回整数,那么它们为什么不返回整数呢
浮点数可以表示
int
范围之外的整数。因此,如果您使用一个太大而无法放入int
的double
参数,对于floor
来说,没有好的方法来处理它。因为所有int
s都可以被上抛到double
而不会丢失,而且double
上的pow
函数的效率从数学角度来看并不低于int
,如果整数大于231-1,则会溢出,如果大于264-1,则会溢出long。也不需要太多的时间就可以让它溢出
双精度是很好的,因为它们可以表示从~10-308到~10308的数字,精度为53位。可能存在一些边缘转换问题(例如,双精度中的下一个完整整数可能无法精确表示),但总的来说,与严格处理整数或长整数相比,您将获得更大的数字范围
在一个类似的主题中,ceil和floor按定义返回整数,那么它们为什么不返回整数呢
出于上述相同的原因-溢出。如果我有一个积分值,它大于我在长时间内所能表示的值,我就必须使用一些能表示它的东西。当我有一个小于我能在长时间内表示的值的整数值时,会发生类似的情况。整数
pow()
和浮点pow()
的最佳实现是非常不同的。C的数学库可能是在考虑浮点协处理器的时候开发的。浮点运算的最佳实现方式是将数字移近1(以加快幂级数的转换),然后将结果移回。对于整数幂,通过执行以下操作,可以在O(log(p))
时间中获得更精确的结果:
// p is a positive integer power set somewhere above, n is the number to raise to power p
int result = 1;
while( p != 0){
if (p & 1){
result *= n;
}
n = n*n;
p = p >> 1;
}
我认为这可以归结为CPU有专门的指令来对浮点数(而不是整数)进行Math.pow运算。对于
Math.pow
,整数(和long)可以转换为double,因此它们会自动处理。我认为它们只是在复制C的数学。h.@markspace:except,在我的编译器接受它之前,我似乎必须将任何int转换为double…我想到int的指数可以变得非常大。BigInteger确实提供指数。当你自己控制它的时候,为什么Java应该为你做任何事情?@djechlin好吧,在这种特殊情况下,它不会为你节省一行代码…在你给出的第二个示例中。。。整型铸造总是四舍五入吗?我认为它被截断了(所以(int)-4.5应该是-4)。不?凯蒂:是的,这两句话都不对。顶部的一个对正数有效,底部的一个对负数有效。@TavianBarnes啊,好的,这更有意义,谢谢,不是所有的都是JNI粘合的。请参阅默认实现。以#round()
为例,计算效率不低,好吧,但可读性/打字效率高,不要为了5^7或其他什么而进行三次强制转换,这会节省很多…@Katie-是的,如果你必须有int
的话,你必须进行结果强制转换,但是你不需要强制转换int
参数-它们是自动向上强制转换的。如果你得到一个长的或者更大的结果呢(int)Math.pow(10300)
即使它同样有效,也不意味着它同样准确。
// p is a positive integer power set somewhere above, n is the number to raise to power p
int result = 1;
while( p != 0){
if (p & 1){
result *= n;
}
n = n*n;
p = p >> 1;
}