【问题标题】:How can I do in javacard a power of 2 with a floating exponent?如何在 javacard 中使用浮动指数计算 2 的幂?
【发布时间】:2014-07-12 15:52:54
【问题描述】:

我需要用 Java Card 中的浮动指数计算 2 的幂。您可能知道,float 类型在 Java Card 规范中是被禁止的。我需要做这样的操作:

short n = 2 ^ (float) (31/4)

预期的nn = 215。 有人知道我该如何计算吗?

【问题讨论】:

  • 指数分数中的除数是否总是2的幂?
  • 是的。除数始终为 4。
  • 在对我的回答进行评论讨论之后,我还有几个问题:1)您使用什么类型的整数算术? 2) 你确定你需要做这个计算吗?

标签: floating-point javacard exponent


【解决方案1】:

正如 Patricia 所说,计算 (2^a)^(1/b) 是有意义的。从您的 cmets 我看到 b 始终为 4。然后它变得简单得多。

因为你总是有 2 的幂,并且总是需要四方根,所以你可以将数字 a 分成 4 的部分(即2^4)和一个余数。其余的只能有 4 个值,为此,您可以使用查找表。我会将其编码为定点值,例如按2^16缩放。

所以,事实上,如果quotient = a // 4remainder = 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^02^0.252^0.52^0.75,然后将结果乘以655362^16),最好四舍五入因此移位不会导致数字略低于您想要的值。

使用示例:

  public static void main(String[] args)
  {
    initfactors();

    int result = calc(31);

    System.out.println(result);
  } 

你的例子:

quotient: 31 / 4 --> 7
remainder: 31 % 4 --> 3
factor: factors[3] --> 110218
result: ((1 << 7) * 110218) >> 16 --> 128 * 110218 / 65536 --> 215. 

【讨论】:

  • +1 这是利用指数除数始终为 4 的一个非常好的方法。
  • @Patricia:它总是 2 的幂这一事实也有很大帮助。
【解决方案2】:

要扩展我的评论并给出部分答案,请考虑将2^(a/b) 计算为(2^a)^(1/b)

2 提高到整数幂很容易:1 &lt;&lt; a。根据所涉及的数字,您可能需要某种形式的扩展精度,例如手动使用两个 int 变量。

剩下的就是计算一个整数的第 b 个根。如果b 是 2 的幂,则可以通过重复的平方根运算来完成,例如使用Newton-Raphson 每个平方根。如果b 可以是任何正整数,则需要更复杂的方法。

解决问题的第 b 个根部分的一种可能方法是二进制搜索。根必须介于 1 和 2^ceil(a/2) 之间。

【讨论】:

  • 嘿,Java Card 主题的 FP 专家,欢迎 :) 由于您的答案可能需要整数(Java Card 上通常不存在),因此可以使用我的 XMas Special answer: JCInteger 进行计算。
  • 我对 Java Card 的了解目前仅限于阅读一篇关于它的文章。我确实了解浮点、算法和 Java。是的 - 我假设使用足够宽的算术类型来包含中间结果。这对我来说似乎很有用,我认为如果它不是内置的,就会有人编写它。
  • 嗯,有 optional 支持 intoptional 支持 javacardx.framework.math.BigNumber(这是非常有限的)。它们通常都不可用。在 Java Card 中假定密码操作应该由操作系统实现(也由于侧信道攻击等),因此对于这类解决方案不需要更大的数字。否则有BigNat,但它对我来说似乎是一个可怕的图书馆。所以选择相当有限。
猜你喜欢
  • 2011-05-24
  • 1970-01-01
  • 2014-02-21
  • 1970-01-01
  • 2012-05-18
  • 2019-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多