【问题标题】:How to check if a data type is at maximum capacity?如何检查数据类型是否处于最大容量?
【发布时间】:2012-10-30 23:58:48
【问题描述】:

这是一个两部分的问题。

  1. 我有一个添加数字的小代码;然而,这些数字的增长速度往往超过long long 的承受能力。

    所以我想我会创建一个类来移动它。

    我的思维过程给出了3long long a, b, c;

    将所有内容添加到c,当c 已满时,将b 加一并将c 设置为零;一旦b 为“满”,将a 加一并将bc 设置为零,依此类推。

    所以,我必须先检查c 是否已满容量,然后再重置它,然后将其添加到b 等等!

    有没有办法检查?

  2. 谁能指出我创建自己的数据类型的正确方向。从视觉上看,我像上面一样将 3 个long longs 放在一起,数据类型将完成我上面所说的。

最后,我想像对待整数一样对待我的新数据类型:

int a = 0;

我希望能够做到

我的数据类型 a = 0;

英语不是我的母语。

【问题讨论】:

  • 还可以看看GMP等库中的BigInteger
  • 您最好的选择是使用不是最大可能大小的类型。换句话说,如果您有两个表示大整数的字节数组,则一次取它们 16 位,并使用 32 位类型执行您的数学运算。很容易检查 32 位结果是否不适合 16 位整数,因此溢出处理很容易。
  • 让我们看看:如果您以 1 GHz 或每秒 1e9 的速度创建数字并运行您的程序 100 年,那么您将生成大约 3e18 个数字,给予或接受。 64 位“signed long long”的范围是 9e18。因此,要超出范围,您要么有更快的计数器/生成器,要么有多个并行运行的数字生成器,或者你的数字有跳跃。

标签: c types struct enums


【解决方案1】:

测试一个整数是否达到容量意味着您的代码效率非常低。例如,要添加 123,您需要进行 123 次增量和 123 次比较。

更好的方法是在执行操作之前确定操作是否会溢出。例如(仅适用于无符号整数):

if(sum <= ULLONG_MAX - a) {
    sum += a;
} else {
    /* It would have overflowed */
}

这是因为ULLONG_MAX - a 不能溢出。当您开始查看有符号整数时,它会成为一个更大的问题,因为LLONG_MAX - a 可能会溢出(如果a 为负数),并且LLONG_MIN - a 也可能溢出(如果a 为正数)。您需要同时测试两种方式:

if( ( a > 0) && (sum <= LLONG_MAX - a) {
    sum += a;
} else if( ( a < 0) && (sum >= LLONG_MIN - a) {
    sum += a;
} else if( a != 0) {
    /* It would have overflowed */
}

一旦您确定它是否会溢出,您就需要处理这种情况。例如;如果您使用多个整数来表示一个更大的整数;然后(对于无符号整数):

if(sum_low <= ULLONG_MAX - a) {
    sum_low += a;
} else {
    sum_low -= (ULLONG_MAX - a) + 1;
    sum_high++;
}

请注意,您必须非常小心,以避免在处理原始(避免)溢出时涉及的临时计算中发生意外溢出。

如果您使用多个有符号整数来表示一个较大的有符号整数,那么溢出处理背后的逻辑就会变得复杂且容易出错。理论上是可以的;但是,最好将数字的符号分开,然后单独对无符号整数进行运算(或其逆运算-例如减去正数而不是添加负数);特别是如果您需要使用 3 个或更多整数来表示一个大整数,或者如果您需要更复杂的运算,例如乘法和除法。

当然,一旦您开始走这条路,您就可以有效地实现自己的“大数字”代码,并且可能应该找到/使用合适的库。

最后,如果您想将新数据类型视为原始数据类型(例如,并且能够执行 mydatatype a = 0; 之类的操作),那么您就不走运了 - C 不能以这种方式工作。从本质上讲,C 是美丽的,因为它不允许对试图阅读/理解代码的人隐藏复杂的事物;如果你想向毫无戒心的受害者隐藏重要信息,你就必须使用像 C++ 这样不那么漂亮的语言。 ;-)

【讨论】:

    【解决方案2】:

    标题&lt;limits.h&gt; 定义,除其他外:

    • LLONG_MAX — 可以存储在(有符号的)long long 中的最大值。它的最小可接受值为 +9223372036854775807 (263-1)。
    • ULLONG_MAX — 可以存储在 unsigned long long 中的最大值。它的最小可接受值为 18446744073709551615 (264-1)。

    您可以通过将它们与其中一个适当的值进行比较来测试您的数字是否已达到这些限制。

    【讨论】:

      【解决方案3】:

      如果您谈论的是签名号码,您可以通过这样做来判断一个号码是否处于“容量”状态:

      if (c > 0 && c + x < 0)
      

      对于无符号数,情况类似:

      if (c + x < c)
      

      在这两种情况下,您只需检查溢出。之后,如果有 溢出,那么您将在 b 中加 1,并将余数 (MAX_LONG_LONG - c) 放回 c。依此类推,从b 过渡到a

      如果不创建自己的结构并将addsubtract 编写为围绕这些结构的函数,我想不出一个简单的方法。

      【讨论】:

      • 您不能依赖签名溢出来按照您的建议行事。通常会,但远不能保证。
      猜你喜欢
      • 2021-06-18
      • 1970-01-01
      • 2011-07-09
      • 2020-03-21
      • 2010-12-25
      • 1970-01-01
      • 2018-10-25
      • 1970-01-01
      • 2011-08-25
      相关资源
      最近更新 更多