【问题标题】:The method add mod 2^512方法add mod 2^512
【发布时间】:2015-05-01 20:49:42
【问题描述】:

它是加模 2^512。你能解释一下为什么我们在这里做>>8然后&oxFF吗? 我知道我数学不好。

int AddModulo512(int []a, int []b)
{
    int i = 0, t = 0;
    int [] result = new int [a.length];
    for(i = 63; i >= 0; i--)
    {
        t = (a[i]) + (int) (b[i]) + (t >> 8);
        result[i] = (t & 0xFF);    //?
    }
    return result;
}

【问题讨论】:

  • 我不明白为什么是oxFF?

标签: java methods add modulo


【解决方案1】:

按位右移 (>>) 对整数的数学效果是除以 2(截断任何余数)。右移 8 次,除以 2^8,即 256。

0xFF 的按位 & 表示结果将被限制在第一个字节,或 0-255 的范围内。

不确定为什么它实际除以 256 时引用模 512。

【讨论】:

    【解决方案2】:

    看起来每个数组中都有64ints,但你的数学是模2^512。 512 除以 64 是 8,因此您只使用每个 int 中的最低有效 8 位。

    这里,t 用于存储可能超过8 位长的中间结果。

    在第一个循环中,t0,所以它不在第一条语句的加法中。还没有东西可以带。但是添加可能会导致需要超过8 位才能存储的值。因此,第二行屏蔽了最不重要的8 位以存储在当前结果数组中。结果原封不动地留给下一个循环。

    t 的先前值在下一次迭代中会做什么?它在加法中用作进位。将其向右移动8 位置会使前一个循环结果中超过 8 的任何位变为当前位置的进位。

    示例,仅使用 2 元素数组,以说明携带:

    [1, 255] + [1, 255]
    

    第一个循环:

    t = 255 + 255 + (0) = 510;     // 1 11111110
    result[i] = 510 & 0xFF = 254;  //   11111110
    

    这里的& 0xFF 只占用最低有效 8 位。在与普通数学的类比中,9 + 9 = 18,但在一个有许多数字的加法问题中,我们说“8 携带 1”。这里的位掩码执行与从 18 中提取“8”相同的功能。

    第二次循环:

    // 1 11111110 >> 8 yields 0 00000001
    t = 1 + 1 + (510 >> 8) = 1 + 1 + 1 = 3; // The 1 from above is carried here.
    result[i] = 3 & 0xFF = 3;
    

    >> 8 提取可能的进位金额。在与普通数学的类比中,9 + 9 = 18,但在一个有许多数字的加法问题中,我们说“8 携带 1”。这里的位移与从 18 中提取“1”的功能相同。

    结果是[3, 254]

    注意最后一次迭代 (i == 0) 的任何进位是如何被忽略的。这实现了模 2^512。上次迭代的任何结转都表示 2^512 并被忽略。

    【讨论】:

      【解决方案3】:

      >> 是按位移位。

      有符号左移运算符“>”将位模式移到 对。位模式由左侧操作数给出,而 右手操作数移位的位置数。未签名的 右移运算符“>>>”将零移到最左边的位置, 而“>>”之后最左边的位置取决于符号扩展。

      & 是按位和

      按位 & 运算符执行按位与运算。

      https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html

      http://www.tutorialspoint.com/java/java_bitwise_operators_examples.htm

      【讨论】:

        【解决方案4】:

        【讨论】:

          【解决方案5】:

          我认为您的问题遗漏了一个非常重要的部分,即数据格式,即数据如何存储在 a[] 和 b[] 中。为了解决这个问题,我做了一些假设:

          • 因为它是模运算,a, b
          • 由于 a 和 b 有 64 个元素,因此每个元素仅使用最右边的 8 位。换句话说,a[i], b[i]

          那么,剩下的就很简单了。只需将每个 a[i] 和 b[i] 视为基数 2^512 加法中的一个数字(每个数字是 8 位),然后通过从右到左逐位相加来执行加法。

          t 是进位变量,它存储最后一位加法的值(带进位)。 t>>8 抛出一个方法,最右边的 8 位已用于最后一次加法,用作当前加法的进位。 (t & 0xFF) 获取 t 的最右边 8 位,用于当前数字。

          由于是模加法,所以最后的进位被扔掉了。

          【讨论】:

            猜你喜欢
            • 2011-12-06
            • 2013-11-14
            • 1970-01-01
            • 1970-01-01
            • 2022-01-14
            • 1970-01-01
            • 2010-11-24
            • 2014-05-15
            • 1970-01-01
            相关资源
            最近更新 更多