【问题标题】:Can condition that a*b>a where (a>b) promise computation without overflow?可以条件 a*b>a where (a>b) 保证计算不会溢出吗?
【发布时间】:2017-08-14 07:34:36
【问题描述】:

问题:给定两个整数a,b(a>b),唯一可以使用的数据类型是int;另外编译器采用二进制补码计算方法。

  1. ab>a 能否保证 ab 的结果正确而不会溢出?
  2. 如果答案是肯定的,我该如何证明?否则,如何找到反例,正确的条件是什么?

【问题讨论】:

    标签: integer-overflow


    【解决方案1】:

    部分回答问题,在 C# 程序中

    using System;
    
    public class Program
    {
        public static void Main()
        {
            int a = 654321;
            int b = -654321;
            var iBool = a * b > a;
            Console.WriteLine(iBool);
        }
    }
    

    条件a * b > a 等于true,这在分析上是错误的。 b是负数,a是正数,所以a*b一定是负数,但绝对值大于b,也就是说a*b不能大于a。但是,实施会另作决定。

    【讨论】:

    • 请注意,如果a 为负,则b 不能为正,因为前提条件是两个整数a, b (a>b)
    • 顺便说一句,关于b 本身也很消极。我只考虑了两者都是否定的情况,但在前提条件内,这也是绝对可能的。
    【解决方案2】:

    没有。

    让我们先看看正数。为了保证承诺是错误的,溢出必须如此之大以至于它不仅溢出而且大于a,因此需要远远超过两倍INT_MAX的东西(准确地说,它需要是大于abs(INT_MIN)+INT_MAX+a)。

    直觉上这似乎不可能发生,但这并不像看起来那么不可能,因为 ab 只需要显着大于位大小的一半int,但不太接近最大值。

    更容易看出,对于否定的 ab,promise 不成立。前置条件a > b 意味着如果a 为负数,那么b 也为负数,因此它们相乘的结果总是正数。

    无论您选择哪个数字,正数总是大于负数,因此只要 ab 均为负数,a*b > a 始终为真,您始终保证不会溢出已经发生了,不管是不是这样。

    除非ab 足够小,否则会发生整数溢出

    取任意两个非特殊但肯定为负的整数,例如 -5'000'000 和 -500'000,它们满足前提条件 a > b
    将它们相乘,你会得到 2'500'000'000'000,它明显溢出(实际上是好几次)。
    结果是 329033728,它肯定大于 -5'000'000,所以你错误地承诺没有发生溢出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-29
      • 2021-04-03
      • 2019-08-29
      • 2019-10-27
      • 2021-10-06
      • 2021-11-28
      相关资源
      最近更新 更多