【问题标题】:Whats a value of x such that both x + 1 == x and x * 2 == x is true? [closed]x 的值是多少,使得 x + 1 == x 和 x * 2 == x 都为真? [关闭]
【发布时间】:2021-06-30 08:18:08
【问题描述】:

标题基本上说明了一切。我的朋友给了我这个挑战,他在他正在做的一些 CTF 中解决了这个挑战。我已经考虑了一段时间,无法弄清楚。此外, INFINITY 不是一个有效的答案。谢谢。

【问题讨论】:

  • 嗯? AFAICT,x + 1 == x,(分组为(x + 1) == x总是为假。句号。如果有 一些解决方案,我们需要更多细节(即括号)和对方程的更多阐述。
  • 可能是float('inf')
  • @CaptainTrojan:OP 排除了这一点,尽管这似乎是一个完全有效的答案。
  • 在某些具有布尔类型的语言中,并且还将任何正数视为等同于True,我可以想象x = True 将是一个有效的解决方案。我不确定那种语言会是什么(它在 Python 中不起作用,因为它不会将所有正整数都视为等于 True)。
  • 那么负无穷大。

标签: c types ctf


【解决方案1】:

在 C 中发生这种情况的唯一方法是:

  • x 是一个无穷大(+∞ 或 -∞)(在不支持无穷大的实现中,HUGE_VAL-HUGE_VAL 等效)。
  • x 是一个 NaN,C 实现对 NaN 使用非 IEEE-754 行为。
  • x 在浮点表示中与无穷大相邻,并使用了合适的有向舍入模式。
  • x+1x*2 溢出以及 C 标准未定义的结果行为恰好将比较报告为 true。
  • x 是未初始化的,因此是不确定的,并且在 x+1 == x 中的 x 的两个外观中采用不同的值,因此比较是正确的,并且在 x*2 == x 中同样采用不同的值或采用零值。
  • x 未初始化并具有自动存储持续时间且其地址未被占用,因此 C 标准未定义该行为,并且结果行为恰好将比较报告为 true。

证明:

除了无穷大之外,这些陈述在实数中在数学上是错误的,因此这不会由实数行为引起。所以它一定是由一些非实数行为引起的,例如溢出、换行、舍入、不确定的值(在每次使用对象时可能不同)或未初始化的值。由于* 被限制为具有算术操作数,我们只需要考虑算术类型。 (在 C++ 中,可以定义一个类来进行比较。)

对于有符号整数,只有在溢出时,+* 才会发生具有完全定义值的非实数行为,因此这是可能的。

对于无符号整数,具有完全定义值的非实数行为仅在存在换行时才会发生在 +* 上。然后,对模 M 进行包装,对于某个整数 x+1 = x+kM >k,所以 1 = kM,这对于任何用于包装的 M 都是不可能的。

对于_Bool 类型,对可能值的详尽测试会消除它们。

对于浮点数,+* 仅在舍入、下溢和溢出以及 NaN 情况下才会发生具有完全定义值的非实数行为。 NaN 从不根据 IEEE-754 规则进行比较,因此它们不能满足这一点,除非 C 标准不要求符合 IEEE-754,因此实现可以选择使比较为真。

x*2 不会下溢,因为它会增加幅度。 x+1 可以以指数范围小于精度的反常浮点格式下溢,但这不会产生x+1 == xx+1 == x 可以通过舍入足够大的x 来满足,但是x*2 必须产生一个不同于x 的值。

这会导致溢出。如果x 是最大可表示有限数(因此是小于无穷大的最大可表示数),并且舍入模式是向下(向-∞)或向零,则x+1 将产生xx*2将产生x,因此比较结果为真。类似地,最大负可表示有限数将满足向上(向+∞)或向零四舍五入的比较。

【讨论】:

    【解决方案2】:

    等式将适用于double x = HUGE_VAL;。从 C99 开始,引用 cppreference.com:

    HUGE_VALFHUGE_VALHUGE_VALL 宏扩展为正浮点常量表达式,这些表达式比较等于浮点函数和运算符在溢出时返回的值

    示例代码:

    #include <math.h>
    #include <stdio.h>
    
    int main() {
        double x = HUGE_VAL;
        printf("%d %d\n", x + 1 == x, 2 * x == x);
        return 0;
    }
    

    Output:

    1 1
    

    【讨论】:

      【解决方案3】:

      使用 C 预处理器求解 x

      #include <stdio.h>
      
      int main() {
      
      #define x  1,1
      
          if (x + 1 == x)
              printf("x + 1 == x is true\n");
      
          if (x * 2 == x)
              printf("x * 2 == x is true\n");
      
          printf("x     = %d\n", x);
          printf("x + 1 = %d\n", x + 1);
          printf("x * 2 = %d\n", x * 2);
      
          return 0;
      }
      

      输出(警告省略:):

      x + 1 == x is true
      x * 2 == x is true
      x     = 1
      x + 1 = 1
      x * 2 = 1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-08-29
        • 2022-03-29
        • 1970-01-01
        • 1970-01-01
        • 2012-06-20
        • 2020-10-07
        • 1970-01-01
        • 2013-03-08
        相关资源
        最近更新 更多