我需要在Java Card中使用浮动指数执行2的幂。您可能知道,Java Card规范中禁止使用float
类型。我需要做这样的操作:
short n = 2 ^ (float) (31/4)
预期的n
是n = 215
。
有人知道我该如何计算呢?
答案 0 :(得分:4)
要扩展我的评论并给出部分答案,请考虑将2^(a/b)
计算为(2^a)^(1/b)
。
将2
提升为整数幂很容易:1 << a
。根据所涉及的数字,您可能需要某种形式的扩展精度,例如手动使用两个int
变量。
离开计算整数的第b个根。如果b
是2的幂,则可以通过重复的平方根操作来完成,例如使用例如每个平方根Newton-Raphson。如果b
可以是任何正整数,则需要更复杂的方法。
问题的第二个根部分的一种可能方法是二分搜索。根必须介于1和2^ceil(a/2)
之间。
答案 1 :(得分:4)
正如帕特里夏所说,计算(2^a)^(1/b)
是有意义的。从你的评论我看到b
总是4.然后它变得更加简单。
因为你总是有2的幂,并且总是需要四根,你可以将数字a除以4的部分(即2^4
)和其余部分。其余的只能有4个值,为此,您可以使用查找表。我会将其编码为固定点值,例如按2^16
缩放。
所以,实际上,如果quotient = a // 4
和remainder = a % 4
计算:2^(quotient) * (2^(remainder / 4) * 65536) // 65536
,其中//
表示整数除法,/
表示浮点除法(我知道)这不是有效的Java,但我使用不同的运算符来显示差异。)
这比使用Newton-Raphson重复计算平方根要快得多,容易得多。
我不太了解Java,所以请原谅语法不正确,但它应该看起来或多或少像这样:
public class MyClass
{
public static int[] factors;
public static void initfactors()
{
factors = new int[4];
factors[0] = 65536; // 2^(0/4) * 65536
factors[1] = 77936; // 2^(1/4) * 65536
factors[2] = 92682; // 2^(2/4) * 65536
factors[3] = 110218; // 2^(3/4) * 65536
}
// Returns 2^(a/4) as integer
public static int calc(int a)
{
int quotient = a / 4;
int remainder = a % 4; // a == 4 * quotient + remainder
int factor = factors[remainder];
// calculate 2^(a/4) * (2^(remainder/4) * 65536) / 65536
return ((1 << quotient) * factor) >> 16;
}
可以这样找到这些因素:您只需使用计算器计算2^0
,2^0.25
,2^0.5
,2^0.75
并将结果乘以{{1} }(65536
),最好是四舍五入,这样移位不会导致数字略低于你想要的数值。
用法示例:
2^16
public static void main(String[] args)
{
initfactors();
int result = calc(31);
System.out.println(result);
}