RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 943320
Accepted
Никита Самоуков
Никита Самоуков
Asked:2020-02-11 05:59:48 +0000 UTC2020-02-11 05:59:48 +0000 UTC 2020-02-11 05:59:48 +0000 UTC

加减法溢出 C++

  • 772

您如何执行 + 并获得溢出?为此做某种条件构造很奇怪。处理器有一个溢出标志。

例如,一般情况下,您需要添加 2 个 2048 位的数字。

理论上这是一个addc命令,但是在c++中怎么做呢?

c++
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    AnT stands with Russia
    2020-02-11T09:22:54Z2020-02-11T09:22:54Z

    C++ 中没有直接的等价物addc。要在纯 C++ 中执行长加法,您可以执行以下操作:

    1. 添加时使用最大整数类型作为数字。通过附加检查捕获溢出:如果总和小于一项(任何一项),则传输到下一位为 1。

      假设我们需要在 64 位平台上使用 256 位整数(最大整数类型是std::uint64_t)。那么这个选项可能看起来像这样

      using Number64 = std::uint64_t [4]; // 256 значащих бит
      
      void add(const Number64 &lhs, const Number64 &rhs, Number64 &res)
      {
        std::uint64_t c;
        res[0] = lhs[0] + rhs[0]; c = res[0] < lhs[0];
        res[1] = lhs[1] + rhs[1] + c; c = c ? res[1] <= lhs[1] : res[1] < lhs[1];
        res[2] = lhs[2] + rhs[2] + c; c = c ? res[2] <= lhs[2] : res[2] < lhs[2];
        res[3] = lhs[3] + rhs[3] + c;    
      }
      

      顺便说一句,GCC 和 MSVC 都猜测adc在翻译此代码以执行加法本身时使用。但是他们没有考虑到这个adc和下一个转移已经产生的事实。

    2. 另外使用小于最大值(最大值的一半)的整数类型作为数字。要执行加法,请将数字转换为最大整数类型。在这种情况下,传输是明确获得的。

      在相同的条件下,这个选项可能看起来像这样

      using Number32 = std::uint32_t [8]; // 256 значащих бит
      
      void add(const Number32 &lhs, const Number32 &rhs, Number32 &res)
      {
        std::uint64_t c;
        res[0] = c = (std::uint64_t) lhs[0] + rhs[0]; 
        res[1] = c = (std::uint64_t) lhs[1] + rhs[1] + (c >> 32);
        res[2] = c = (std::uint64_t) lhs[2] + rhs[2] + (c >> 32);
        res[3] = c = (std::uint64_t) lhs[3] + rhs[3] + (c >> 32);
        res[4] = c = (std::uint64_t) lhs[4] + rhs[4] + (c >> 32);
        res[5] = c = (std::uint64_t) lhs[5] + rhs[5] + (c >> 32);
        res[6] = c = (std::uint64_t) lhs[6] + rhs[6] + (c >> 32);
        res[7] = (std::uint64_t) lhs[7] + rhs[7] + (c >> 32);
      }
      
    3. 可以使第二个选项在加法运算中表现得不那么“浪费”:以最大整数类型存储位,但同时使每个位的最高有效位未使用。也就是说,例如,每个std::uint64_t字将仅存储 63 个有用位。并且每个高位都将未被使用:它被保留以便进位到达那里。同时,要表示一个 256 位的值,需要 5 个std::uint64_t字,而不是 4 个

      using Number63 = std::uint64_t [5]; // 320 бит, 315 значащих
      
      void add(const Number63 &lhs, const Number63 &rhs, Number63 &res)
      {
        res[0] = lhs[0] + rhs[0];
        res[1] = lhs[1] + rhs[1] + (res[0] >> 63); res[0] &= 0x7FFFFFFFFFFFFFFF;
        res[2] = lhs[2] + rhs[2] + (res[1] >> 63); res[1] &= 0x7FFFFFFFFFFFFFFF;
        res[3] = lhs[3] + rhs[3] + (res[2] >> 63); res[2] &= 0x7FFFFFFFFFFFFFFF;
        res[4] = lhs[4] + rhs[4] + (res[3] >> 63); res[3] &= 0x7FFFFFFFFFFFFFFF;
        res[4] &= 0x7FFFFFFFFFFFFFFF;
      }
      

      但是我认为这种在位序列中带有“漏洞”的表示并没有多大意义。这也将使其他操作难以实施。

    只要只使用硬件平台本机支持的类型(即最高std::uint64_t64 位平台的类型),第一个选项似乎是最有效的。但是,如果编译器为扩展整数类型提供模拟支持(例如,__uint128_t64 位平台上的 GCC 支持)并且编译器擅长优化此类类型的操作,那么第二个选项将其__uint128_t用作“最大值”类型,可以和第一个竞争。

    • 1

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    根据浏览器窗口的大小调整背景图案的大小

    • 2 个回答
  • Marko Smith

    理解for循环的执行逻辑

    • 1 个回答
  • Marko Smith

    复制动态数组时出错(C++)

    • 1 个回答
  • Marko Smith

    Or and If,elif,else 构造[重复]

    • 1 个回答
  • Marko Smith

    如何构建支持 x64 的 APK

    • 1 个回答
  • Marko Smith

    如何使按钮的输入宽度?

    • 2 个回答
  • Marko Smith

    如何显示对象变量的名称?

    • 3 个回答
  • Marko Smith

    如何循环一个函数?

    • 1 个回答
  • Marko Smith

    LOWORD 宏有什么作用?

    • 2 个回答
  • Marko Smith

    从字符串的开头删除直到并包括一个字符

    • 2 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5