9

我正在寻找CD的现有实现,或在实现具有浮点语义的有符号和/或无符号整数类型方面的建议。

也就是说,一个整数类型在做算术时表现得像浮点类型:溢出产生无穷大-infinity表示有符号下溢)而不是环绕或具有未定义的行为,未定义的操作产生NaN等。

本质上,一种浮点版本,可呈现数字的分布均匀地落在数轴上,而不是聚集在 0 附近。

此外,所有操作都应该是确定性的;任何给定的二进制补码 32 位架构都应该为相同的计算产生完全相同的结果,而不管其实现如何(而浮点可能并且通常会产生略有不同的结果)。

最后,性能是一个问题,这让我担心潜在的“bignum”(任意精度)解决方案。

另请参阅:定点饱和算法

4

4 回答 4

3

我不知道任何现有的实现。

但我想实现它将是(在 D 中)的问题:

enum CheckedIntState : ubyte
{
    ok,
    overflow,
    underflow,
    nan,
}

struct CheckedInt(T)
    if (isIntegral!T)
{
    private T _value;
    private CheckedIntState _state;

    // Constructors, getters, conversion helper methods, etc.

    // And a bunch of operator overloads that check the
    // result on every operation and yield a CheckedInt!T
    // with an appropriate state.

    // You'll also want to overload opEquals and opCmp and
    // make them check the state of the operands so that
    // NaNs compare equal and so on.
}
于 2012-11-24T18:24:20.583 回答
2

一种解决方案可能是使用抽象数据类型实现多精度算术。David Hanson的《C Interfaces and Implementations 》一书有一章(接口和实现)介绍了 MP 算术。

使用缩放整数进行计算也是一种可能。您也许可以使用他的任意精度算术,尽管我相信这个实现不会溢出。您可能会耗尽内存,但这是另一个问题。

在任何一种情况下,您都可能需要调整代码以准确返回您想要的溢出等。

源代码(MIT 许可证)

该页面还有一个从 amazon.com 购买该书的链接。

于 2012-11-24T23:09:38.007 回答
2

除了未定义的操作产生 NaN 的部分之外,饱和算术可以满足您的需求;这将是有问题的,因为大多数饱和实现使用完整的数字范围,因此没有剩余的值可以为 NaN 保留。因此,除非您有一个额外的“此值是否为 NaN”字段,否则您可能无法轻松地在饱和硬件指令的背面构建它,这是相当浪费的。

假设您对 NaN 值的想法深信不疑,那么所有边缘情况检测可能都需要在软件中进行。对于大多数整数运算,这非常简单,特别是如果您有更广泛的可用类型(假设long long严格大于任何整数类型myType):

myType add(myType x, myType y) {
    if (x == positiveInfinity && y == negativeInfinity ||
        x == negativeInfinity && y == positiveInfinity)
        return notANumber;
    long long wideResult = x + y;
    if (wideResult >= positiveInfinity) return positiveInfinity;
    if (wideResult <= negativeInfinity) return negativeInfinity;
    return (myType)wideResult;
}
于 2012-11-24T18:26:34.710 回答
0

饱和算术满足了一半的要求,例如 ARM 指令、MMX 和 SSE。

正如斯蒂芬佳能所指出的,需要额外的元素来检查溢出/NaN。一些指令集(至少是 Atmel)btw 有一个标记来测试溢出(可用于区分 inf 和 max_int)。也许“Q”+ 0 可以标记为 NaN。

于 2012-11-24T18:24:52.130 回答