我正在寻找 C 或 D 的现有实施方案,或实施,签名和/或无符号整数类型的建议浮点语义。
也就是说,在执行算术时表现为浮点类型的整数类型:溢出产生无穷大 ( -infinity 签名的下溢)而不是环绕或具有未定义的行为,未定义的操作产生 NaN 等。
本质上是一个浮点版本,其中可呈现数字的分布均匀地落在数字线上,而不是在0附近聚合。
此外,所有操作都应确定性;任何给定的二进制补码32位架构应该为相同的计算产生完全相同的结果,无论其实现如何(而浮点可能,并且通常会产生稍微不同的结果)。
最后,表现是一个问题,让我担心潜在的“bignum”(任意精度)解决方案。
另请参阅:定点和饱和算术。
答案 0 :(得分: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.
}
答案 1 :(得分: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;
}
答案 2 :(得分:2)
一种解决方案可能是使用抽象数据类型实现多精度算术。 David Hanson的书籍 C接口和实现有一个MP算法的章节(接口和实现)。
使用缩放整数进行计算也是可能的。你可能能够使用他的任意精度算术,虽然我相信这个实现不会溢出。你可能会耗尽内存,但这是一个不同的问题。
在任何一种情况下,您可能需要调整代码以准确返回溢出等所需的内容。
Source code(麻省理工学院执照)
该页面还有一个从amazon.com购买该书的链接。
答案 3 :(得分:0)
在饱和算术中满足一半的要求,这些算法在例如ARM指令,MMX和SSE。
正如Stephen Canon所指出的那样,需要额外的元素来检查溢出/ NaN。一些指令集(Atmel至少)btw有一个粘滞标志来测试溢出(可用于区分inf和max_int)。也许“Q”+ 0可能标志着NaN。