0

int のペアを double にエンコードしたいと思います。たとえば、関数を渡したいとします。

foo(int a, int b)

しかし、代わりに、2 つの int を表すために 1 つの double だけが必要です (つまり) :

foo(double aAndB)

現在、小数点以下のいずれかの側に 1 つの int を配置し (つまり、10 と 15 は 10.15 になります)、それを文字列ストリームに変換して、2 つの数値をトークン化して抽出しています。

ただし、10 や 10 などの数値に関しては、これには明らかな欠陥があります。つまり、10.1 になります。

関数に2つのintを表すdoubleを渡すことができるように、いくつかのトリッキーな数学的方法でこれを行う方法はありますか?

ありがとう。

4

6 に答える 6

5

(通常) double には 64 ビットが含まれ、各 int には 32 ビットがあるため、ビットを double に直接格納するだけでよいと考えるでしょう。たとえば、次のようになります。

int32_t i1 = rand();
int32_t i2 = rand();
int64_t x = (((int64_t)i1)<<32) | ((int64_t)i2);
double theDouble;
memcpy(&theDouble, &x, sizeof(theDouble));

...そしてそれを「ほぼうまくいく」。つまり、i1 と i2 の多くの可能な値に対して問題なく動作しますが、すべての値に対してではありません。特に、IEEE754 浮動小数点形式の場合、指数ビットが 0x7ff に設定されている値はすべて「NaN」を示すものとして扱われ、浮動小数点ハードウェアは異なる NaN に相当するビットパターンを変換して、優先するパターンに戻すことができます (実際に変換します)。 double を引数として渡すときの NaN ビットパターンなど。

このため、2 つの 32 ビット整数を double に詰め込むと、ほとんどの場合はうまくいくように見えますが、考えられるすべての入力値でテストすると、値が double 内に留まっている間に予期せず変化する場合がいくつか見つかります。それらを再度デコードすると、異なる値として出てきました。

もちろん、double の仮数ビットのみを設定するように注意することでこれを回避できますが、それでは整数あたり 26 ビットしか得られないため、+/- 33,554,432 程度の整数値しか格納できません。ユースケースによっては、それで問題ないかもしれません。

私のアドバイスは、あなたがやろうとしていることは何でもするための別の方法を見つけることです. 非浮動小数点データを浮動小数点変数に格納すると、特にコードを移植可能にしたい場合に問題が発生します。

于 2012-05-25T06:44:55.470 に答える
4

運が良ければ、int が double の半分である場合、次のように int を格納できます。

int a = 10;
int b = 20;
ダブル d;

*(int *)&d = a;
*((int *)&d + 1) = b;

int outa = *((int *)&d);
int outb = *(((int *)&d) + 1);
printf("%d %d\n", outa, outb);

これは一般的には機能しません/移植性。double と int のビット数が同じ場合、必要なものは不可能です。

于 2012-05-25T06:34:20.563 に答える
3

double は、53 ビットまでの整数を正確に表すことができます。26 ビットと 27 ビットの整数を保持したい場合は、非常に簡単です。double combined = bits27*67108864.0 + bits26;

67108864 は 2^26 であることに注意してください。

于 2012-05-25T06:33:07.660 に答える
1

次のように共用体を定義してみてください。

struct two_int {
    int a;
    int b;
};

union encoding {
    struct two_int a;
    double c;
};

ただし、このようにすると、移植性に問題が生じる可能性があります。このアプローチがあなたのケースに適しているかどうかを再確認してください。

于 2012-05-25T06:35:08.937 に答える
1

バイナリマスクを使用してそれを行い、「ダブル」から情報を抽出できます。

例えば:

double encode(int a, int b)
{
    double d = 0;
    d = d | a; 
    d = d | (b << 8);
    return d;
}

double decode(double d)
{
    a = d & 0xFF;
    b = (d >> 8) & 0xFF;
}

エンコード部分では、a は double 変数 d の下位 8 ビットになり、b は d の上位 8 ビットになります。

于 2012-05-25T06:35:13.720 に答える
0

この1つのパラメーターに常に2つのintを渡す場合は、doubleを渡すことは意味がありません。代わりに、2つのintを別々のintとして渡すか、構造体でラップします。

あなたがそれをしている方法では、真のダブルと2つのintの違いを検出する機会がありません。したがって、上記で説明したことを実行しても、機能が失われることはないと結論付けます。

于 2012-05-25T06:36:46.283 に答える