【问题标题】:Can I use 128-bit integer in MSVC++? [duplicate]我可以在 MSVC++ 中使用 128 位整数吗? [复制]
【发布时间】:2014-07-09 15:02:53
【问题描述】:

我正在使用 Visual Studio 2010 编写 C++/MFC 应用程序,我需要维护一个累积的 running total,用于计算平均传输率,如下所示:

//Let's assume that INT128 is a 128-bit integer type
static INT128 iRunningTotal = 0;
static INT128 iCounter = 0;

LONGLONG iteration_get_current_average(LONGLONG iRate)
{
    //May be called repeatedly...
    iRunningTotal += iRate;
    iCounter++;

    //Calculate the current average
    return iRunningTotal / iCounter;
}

我搜索了C++ 128-bit integer,几乎所有人们建议使用 Boost 库。嗯,这是一种可能性,但我不熟悉它,并且不会在我的项目中的任何其他地方使用它。

除了 Boost,我很好奇,有没有办法用纯 C/C++ 做到这一点?

【问题讨论】:

  • “我很好奇,有没有办法用纯 C/C++ 做到这一点?” - 答案显然是肯定的,因为 C++ 是图灵完备的。但是,如果您不想使用库,则需要自己制作一个。
  • 对于这种特殊情况,您实际上需要一个 128 位整数的可能性很小。传输速率很少(如果有的话)足以超过 64 位整数的容量,LONGLONG 就是这样。一个 64 位整数可以保存最多 16 个 exabytes 的值。
  • 并且通过“极不可能” .. 还有 1) iRate 可以缩减(例如 K/s、M/s)和 2) 双倍有 很多 更宽ranger 比 128 位整数,尽管“大值”的准确性损失。 (而且绝对没有理由让 iCounter 变得那么大。)
  • 传输速率通常以浮点数表示给用户,很少以每次原始字节数表示,因此将速率计算为每次 kb/mb/gb 将大大减少所需整数的大小(越高单位,所需的位数越小)。
  • 使用 64 位无符号整数,您最多可以数 18 exabit。根据cisco,这是到 2017 年世界许多地区预计的每月互联网流量,因此它可能类似于目前的全球每月流量。你真的认为你需要的不止这些吗?

标签: c++ visual-c++ mfc


【解决方案1】:

我将抛​​开这是否是个好主意的问题,或者您测量的物理量在理论上是否可能超过 2^63 或 10^19 或大约的值。我相信你有你的理由。那么在纯 C/C++ 中你有哪些选择呢?

答案是:不多。

  • 128 位整数不是任何标准的一部分,我所知道的编译器也不支持它们。
  • 64 位双精度会为您提供动态范围(10^308 左右)。如果您不需要确切的答案,这是一个很好的选择。不幸的是,如果您有一个包含足够多的零的数字,然后向其添加一个,它就不会改变。
  • 浮点处理器原生支持 80 位双精度,这为您提供了 63 位尾数以及扩展的动态范围。

那么,自己动手做 128 位整数运算怎么样?你真的必须是一个受虐狂。做加法和减法很容易(注意你的进位),并且稍微考虑一下,做乘法并不难。除法完全是另一回事。这非常困难,并且可能的结果是出现类似于 1990 年代 Pentium 错误的错误。

您可以毫无困难地将计数器累积为两个(或更多)64 位整数。然后将它们转换为双精度数以进行最后的计算。这应该不会太难。

那之后恐怕要去图书馆购物了。您提到了 Boost,但是周围有更多专业的库,例如 cpp-bigint。

不出所料,这个问题之前有人问过,并且有一个很好的答案:Representing 128-bit numbers in C++

【讨论】:

  • 谢谢。感谢您抽出宝贵时间来实际解决这个问题。
  • 嗯...实现 128 位除法和其他基本整数运算并不难。为了速度,您显然会在 asm 中执行此操作。 Here's x64 example.
  • @ahmd0:我非常不同意。正如我所说,实现除法很难,测试它的正确性更难。英特尔失败了,很多年前我们也失败了(谁知道 Knuth 有问题?)。您的代码可能正确,也可能不正确,谁能告诉您?广泛使用和经过测试的库是必经之路。
  • @david.pfx 花时间测试事物的人可以说出来。您认为广泛使用和测试的库所做的测试与您所做的不同......?由于缺乏对测试的实际关注,所有这些“事故”都是微不足道的无能。您可以在前 5 个人注意到您的库存在之前编写好的测试并捕获所有错误。如果你有一些数字并在你的代码中划分它,但根据你的手工操作结果显然是错误的,我想知道你怎么知道它是否是错误的?
  • @Sahsahae:那你显然从来没有真正做到过;我有。数值库的测试空间是巨大的,远远超出了“好的”测试实践。你认为你比英特尔更好吗?您会在将 Pentium 变成硅之前检测到它吗?显然不是。
【解决方案2】:

让我们尝试计算您的数字可能变得大到足以溢出 64 位数字的点。

假设您每微秒进行一次测量。以每秒 100 万次增量的速率,64 位数字溢出需要 264/1'000'000 秒。这计算了超过 50 万年。即使将速率提高到每纳秒一次,也需要 500 多年。

对于运行总数,您可以(理论上)早一点用完。例如,如果你有 100 Gigabit 以太网,并且一直以最大理论带宽运行,那么你将在不到 47 年内(稍微)用完。

如果您将自己限制在我们大多数人实际上能够负担得起的技术上,那么大多数使用处理的最快传输速率大约是与 SSD 之间的传输速率。假设您有可以处理它的驱动器,最新的 SATA Express 规范支持高达 16 Gb/s 的传输。在用完 64 位整数的全部范围之前,您需要使 24/7 饱和超过 200 年。

嗯...也许我们应该看看主内存。让我们假设 4 个通道的最快 DDR 4 内存尚未指定,并且(一如既往)非常不切实际的假设,即您将保持它以 24/7 的最大理论带宽运行。有了这个,您仍然可以一次计算所有进出内存的传输超过 4 年,然后您将面临 64 位整数溢出的任何危险。

当然,您可以尝试对 CPU 和 RAM 进行超频以更快地到达那里,但这可能是一场失败的游戏 - 任何超过非常最适度的超频将可能会降低零件的预期寿命,因此机器可能会在 64 位整数溢出之前死机。

底线:您对 128 位整数的需求充其量似乎值得怀疑。

【讨论】:

    猜你喜欢
    • 2013-08-28
    • 2013-04-11
    • 2023-01-04
    • 2012-08-25
    • 2013-09-23
    • 2015-02-19
    • 2021-10-22
    • 2011-05-01
    相关资源
    最近更新 更多