【问题标题】:Modulo (%) in C returning undefined result compared to the same function in Python? [duplicate]与Python中的相同函数相比,C中的模(%)返回未定义的结果? [复制]
【发布时间】:2021-12-28 17:44:50
【问题描述】:

我正在编写一个(我认为的)是一个实现仿射密码的简单程序,并且遇到了一个问题,即我没有从 C89 中的模数中得到预期的结果。

int main()
{
    foo(10);
    return 0;
}

int foo(int enc)
{
    int a = 5, b = 22, inv_a = 77, result;
    result = (inv_a * (enc - b)) % 128;
    printf("result = %d = %c\n", result, result);
    return result;
}

上面的结果是-28(未定义的行为?)

同时,python中的相同功能:

def foo(enc):
    a = 5
    b = 22
    inv_a = 77
    result = (inv_a * (enc - b)) % 128
    print(result)

foo(10)

返回我的预期结果 100。在调试过程中,我发现结果与使用模数相同。我不知道的 C 模中发生了什么?

【问题讨论】:

  • 它不是未定义的 - 它只是定义与您预期的不同。 (注意 100 和 -28 是全等的 mod 128,所以在某种数学意义上,两者都是“正确的”。)
  • "C modulo" --> C 缺少欧几里得模数:What's the difference between “mod” and “remainder”? 可能有助于理解 C。

标签: c encryption cryptography c89 mod


【解决方案1】:

C 中的% 运算符实际上并不执行取模,而是执行除法的余数。后者允许负值。

具体而言,来自C standard 的第 6.5.5p6 节:

表达式(a/b)*b + a%b 应等于a

【讨论】:

  • Signed remainder of C-style division is as much of a modulo operator as unsigned remainder. 如果你想要一个真正的数学家的模,那么结果应该是一个等价类。例如,x 模 y 是所有整数 n 的集合,使得 n 等价于 x 模 3,即 { n | ∃ k∈Z : n = x+ky }。因此,结果不是一个单一的数字,而是一个集合。数学家可以将此集合写为 [x]_y,其中“_y”表示 y 作为下标。 [x]_y = { n | ∃ k∈Z : n = x+ky }。那么[−28]_128 = [100]_128;他们是同一组……
  • ... 所以[x]中的x只是一个代表,数学家并不挑剔选择哪个代表。只有当模数适用于计算并且需要整体的单个代表时,才必须做出选择。然后,就数学家而言,任何返回正确代表的运算都是模运算的代理。 (只是一个代理,因为如上所述,真正的结果将是一个集合。)
  • @EricPostpischil:如果 x 与 y mod m 一致,则应设计适当的模运算,使 (x%m) 和 (y%m) 相等。出于许多目的,最方便的此类操作会将等价类映射到 0 到 m-1 范围内的整数,包括 0 到 m-1,但对于其他一些应用程序,从 floor(-m/2) 到 floor((m-1 )/2) 也很方便。然而,将全等 mod m 的对象映射到不同值的操作并不是真正的模操作。
猜你喜欢
  • 2018-03-27
  • 2021-11-21
  • 2018-12-06
  • 2020-07-28
  • 2014-01-25
  • 2021-05-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多