web-dev-qa-db-ja.com

浮動小数点から2進値(C ++)

2.25125のようなC++の浮動小数点数と、浮動小数点をメモリに格納するために使用されるバイナリ値で満たされたint配列(IEEE 754)を取得したいと思います。

したがって、数値を取得して、floatのバイナリ値を持つint num [16]配列になります。num[0]は1になりますnum [1]は1になりますnum [2]は0になりますnum [3 ]は1などになります。

Intを配列に入れるのは難しくありません。floatのバイナリ値を取得するプロセスだけが行き詰まっています。 float変数であるメモリ内のバイナリを読み取ることができますか?そうでない場合は、C++でこれを行うにはどうすればよいですか?

編集:この方法で比較を行う理由は、C++でビット演算を行う方法を学びたいからです。

17
user58389

ユニオンとビットセットを使用します。

#include <iostream>
#include <bitset>
#include <climits>

int main()
{
    union
    {
        float input; // assumes sizeof(float) == sizeof(int)
        int   output;
    } data;

    data.input = 2.25125;

    std::bitset<sizeof(float) * CHAR_BIT> bits(data.output);
    std::cout << bits << std::endl;

    // or
    std::cout << "BIT 4: " << bits[4] << std::endl;
    std::cout << "BIT 7: " << bits[7] << std::endl;
}

配列ではないかもしれませんが、配列を使用しているかのように、[]演算子を使用してビットにアクセスできます。

出力

$ ./bits
01000000000100000001010001111011
BIT 4: 1
BIT 7: 0
24
Martin York
int fl = *(int*)&floatVar; //assuming sizeof(int) = sizeof(float)

int binaryRepresentation[sizeof(float) * 8];

for (int i = 0; i < sizeof(float) * 8; ++i)
    binaryRepresentation[i] = ((1 << i) & fl) != 0 ? 1 : 0;

説明

(1 << i)は、値1iビットを左にシフトします。 &演算子は ビット単位で オペランドの。

forループは、floatの32ビットごとに1回実行されます。毎回、iは値を抽出したいビットの数になります。ビット単位と数および1 << iを計算します。

番号が1001011、およびi = 2であると想定します。

1<<iは0000100に等しくなります

  10001011
& 00000100
==========
  00000000

if i = 3 then:

  10001011
& 00001000
==========
  00001000

基本的に、結果は、ithビットが元の数値のithビットに設定され、他のすべてのビットがゼロの数値になります。結果はゼロになります。これは、元の数値のi番目のビットがゼロまたは非ゼロであることを意味します。つまり、実際の数値のi番目のビットは1に等しくなります。

15
Mehrdad Afshari

stlを使用した他のアプローチ

#include <iostream>
#include <bitset>

using namespace std;
int main()
{
    float f=4.5f;
    cout<<bitset<sizeof f*8>(*(long unsigned int*)(&f))<<endl;
    return 0;
}
4
test30

特定の浮動小数点表現が必要な場合は、ビットコピーではなく、浮動小数点自体から意味的に構築する必要があります。

c0x標準: http://c0x.coding-guidelines.com/5.2.4.2.2.html 浮動小数点数の形式を定義していません。

2
Douglas Leeder

Float変数であるメモリ内のバイナリを読み取ることができますか?

はい。それにポインタをintポインタに静的にキャストし、結果からビットを読み取ります。 C++のIEEE754 floatタイプは32ビットです。

2
codekaizen

Unsigned charを使用して、floatをバイトごとに整数配列に読み込むことができます。

unsigned int bits[sizeof (float) * CHAR_BIT];
unsigned char const *c = static_cast<unsigned char const*>(
    static_cast<void const*>(&my_float)
);

for(size_t i = 0; i < sizeof(float) * CHAR_BIT; i++) {
    int bitnr = i % CHAR_BIT;
    bits[i] = (*c >> bitnr) & 1;
    if(bitnr == CHAR_BIT-1)
        c++;
}

// the bits are now stored in "bits". one bit in one integer.

ちなみに、(別の回答にコメントするときに)ビットを比較したいだけの場合は、memcmpを使用してください。

memcmp(&float1, &float2, sizeof (float));

この回答のコメントを見ると( Floating Point to Binary Value(C++) )これを行う理由は、2つの値のビット単位の比較を実行するためです。

#include <iostream>

int main()
{
    union Flip
    {
         float input;   // assumes sizeof(float) == sizeof(int)
         int   output;
    };

    Flip    data1;
    Flip    data2;
    Flip    data3;

    data1.input = 2.25125;
    data2.input = 2.25126;
    data3.input = 2.25125;

    bool    test12  = data1.output ^ data2.output;
    bool    test13  = data1.output ^ data3.output;
    bool    test23  = data2.output ^ data3.output;

    std::cout << "T1(" << test12 << ") T2(" << test13 << ") T3(" << test23 << ")\n";


}
2
Martin York

Intポインターをfloatポインターにキャストすれば、完了です。

(int配列としては宣言しませんが、void *を使用して、メモリが他の値のダンプグラウンドとして使用されていることを明確にします。)

ちなみに、フロートの配列だけを使ってみませんか?

1
benjismith

Floatとunsignedlongの和集合を作成します。 floatメンバーの値を設定し、他の回答ですでに説明されているように、unsignedlong値のビットを繰り返し処理します。

これにより、キャスト演算子が削除されます。

1
Noel Walters

さて、C++には、なんらかの問題なしにフロートを格納するための本当に安全な方法があるとは思いません。マシン間の移動に関しては、効率的であり、大容量のストレージを使用せずに簡単に保管できます。

非常に正確ですが、実際には非常識な値をサポートしません。どの場所でも最大7桁まで使用できますが、どちらの側でも7桁を超えることはできません。左側では、不正確な結果が表示されます。右側では、読み取り時にエラーが発生します。エラーを解決するには、書き込み中にエラーをスローするか、読み取りで「buffer [idx ++]&0x7」を実行して、0と7の境界を超えないようにします。 「&0x7」は2の累乗から1を引いたものであるため、のみ機能することに注意してください。これは2 ^ 3-1です。これは、これらの値でのみ実行できます。 0、1、3、7、15、31、63、127、255、511、1023など..

したがって、これを使用するかどうかはあなた次第です。必要なほとんどの値を取得するための安全な方法だと感じました。以下の例は、4バイト配列に変換される方法を示していますが、C++の場合はchar *になります。除算を実行したくない場合は、POWERS_OF_TEN配列を10進数と倍数の2次配列に変換できます。

const float CacheReader::POWERS_OF_TEN[] = 
{
    1.0F, 10.0F, 100.0F, 1000.0F, 10000.0F, 100000.0F, 1000000.0F, 10000000.0F
};

float CacheReader::readFloat(void)
{
    int flags = readUnsignedByte();
    int value = readUnsignedTriByte();
    if (flags & 0x1)
        value = -value;
    return value / POWERS_OF_TEN[(flags >> 1) & 0x7];
}

unsigned __int32 CacheReader::readUnsignedTriByte(void)
{
    return (readUnsignedByte() << 16) | (readUnsignedByte() << 8) | (readUnsignedByte());
}

unsigned __int8 CacheReader::readUnsignedByte(void)
{
    return buffer[reader_position] & 0xFF;
}

void CacheReader::writeFloat(float data)
{
    int exponent = -1;
    float ceiling = 0.0F;

    for ( ; ++exponent < 8; )
    {
        ceiling = (POWERS_OF_TEN[exponent] * data);
        if (ceiling == (int)ceiling)
            break;
    }

    exponent = exponent << 0x1;
    int ceil = (int)ceiling;
    if (ceil < 0)
    {
        exponent |= 0x1;
        ceil = -ceil;
    }
    buffer[writer_position++] = (signed __int16)(exponent);
    buffer[writer_position++] = (signed __int16)(ceil >> 16);
    buffer[writer_position++] = (signed __int16)(ceil >> 8);
    buffer[writer_position++] = (signed __int16)(ceil);
}
0
Jeremy Trifilo

ポインタをキャストすることでもできます。ここに小さな例があります

#include <iostream>
#include <bitset>

using namespace std;

int main(){
    float f = 0.3f;
    int* p = (int*)&f;
    bitset<32> bits(*p);
    cout << bits << endl;
}
0
nmd_07