9

CまたはDの既存の実装、または浮動小数点セマンティクスを使用した符号付きおよび/または符号なし整数型の実装に関するアドバイスを探しています。

つまり、演算を行うときに浮動小数点型と同じように動作する整数型です。オーバーフローは、ラップアラウンドや未定義の動作ではなく、無限大(符号付きアンダーフローの場合は-infinity ) を生成し、未定義演算はNaNなどを生成します。

本質的には、表示可能な数値の分布が 0 の周りに集まるのではなく、数直線上に均等に収まるバージョンの浮動小数点です。

さらに、すべての操作は決定論的である必要があります。任意の 2 の補数 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

1つの解決策は、抽象データ型を使用して多倍長演算を実装することです。DavidHansonによる本CInterfacesand Implementationsには、MP演算の章(インターフェースと実装)があります。

スケーリングされた整数を使用して計算を行うことも可能です。この実装はオーバーフローできない思いますが、彼の任意精度の演算を使用できる可能性があります。メモリが不足する可能性がありますが、それは別の問題です。

いずれの場合も、オーバーフローなどで必要なものを正確に返すようにコードを微調整する必要がある場合があります。

ソースコード(MITライセンス)

そのページには、amazon.comから本を購入するためのリンクもあります。

于 2012-11-24T23:09:38.007 に答える
2

飽和演算は、未定義の演算が NaN を生成する部分を除いて、必要なことを行います。ほとんどの飽和実装は完全な数値範囲を使用し、NaN 用に予約する値が残っていないため、これは問題になるでしょう。したがって、追加の「is this value 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などで実装される飽和演算で満たされます。

Stephen Canonも指摘しているように、オーバーフロー/NaNをチェックするには追加の要素が必要です。一部の命令セット(少なくともAtmel)には、オーバーフローをテストするためのスティッキングフラグがあります(infとmax_intを区別するために使用できます)。そして、おそらく「Q」+0はNaNをマークする可能性があります。

于 2012-11-24T18:24:52.130 に答える