3

入力として float を取り込んで、基数 2 の科学的表記法で同等の表現を出力しています。これは IEEE 32 ビットで、31 符号ビット、23 ~ 30 指数 (127 オフセットあり)、0 ~ 22 仮数 (暗黙の先行 1 あり) です。

意味がよくわからない条件の 1 つは、「仮数部には暗黙の先頭に 1 を追加する必要がある」というものです。

私が実際に学んだことは、フロートを小数部分と小数部分に分割し、それらのバイナリ表現を別々に取得することだけです。

これを行う方法がわからないので...実際にコーディングすることはできません。そうするための何らかのアルゴリズム、またはコード自体に関するヒントや情報をいただければ幸いです。ありがとう。

サンプル:

Input: -40.1
Output: -1.01000000110011001100110 E101

Input: 13.5
Output: 1.10110000000000000000000 E11

編集: 127 オフセットは、過剰な 127 表記を意味しますよね? 私の本には超過 128 しかありませんが、とにかく違いがわかりません...

4

4 に答える 4

2

これは宿題のように聞こえるので、すべての作業を行うつもりはありません。しかし、私はあなたを始めさせます、そしてあなたはギャップを埋めることができます. そのため、c++ には共用体と呼ばれる便利なデータ型があり、これを使用すると、複数のデータ型を同じスペースに配置できます。これは、浮動小数点数のビット表現を見たい場合などに非常に便利です。次のコードは、浮動小数点数のバイナリ表現を出力します。

#include <iostream>
using namespace std;
union b{
   float flo;
   int integ;
};
int main(){

  b thing;
  thing.flo=-40.1;
  for(int i=31;i>=0;i--){
    if((thing.integ & (1 << i)))
      cout << 1;
    else
      cout << 0;
  }
  cout << endl;
}

あとは、仮数と指数を抽出するだけです。ルーチンを 1 回実行して仮数を生成し、再度指数を生成することができます。両方を行う方法と注意事項について簡単に説明します。

仮数を生成するときは、IEEE が 0 の予約コードを持つ隠し 1 を使用することに注意してください。そのため、ビット表現にない余分な 1 が常に存在することになります。基本的に、符号ビットをチェックして - または + に応じて出力し、次に 1. 仮数にスキップして、それに続くものを出力します。次に、23 ~ 30 ビットに戻り、それを int に変換して、各ビットに 2^i を掛けます (23 ビットは 0、24 ビットは 1 など)。 int からオフセットを減算します。次に、以前のアウトライン メソッドを使用して指数のバイナリ表現を出力し、1 に到達するまで出力しないことを検討します。これが役立つことを願っています。

于 2010-10-03T18:45:01.073 に答える
0

これを行う最もクリーンな方法の 1 つは、ビットマスキングを使用することです。おそらく、より良い方法はビットフィールドを使用することです。浮動小数点形式を表す構造体を定義できます。

struct float_layout {
  int mantisa : 23
  int exp : 8
  int sign : 1
};

次に、float を取得して、この構造体にキャストします。

float b = input;
float_layout layout = *static_cast<float_layout *>(&b)

これにより、データのビットを変更せずに再解釈します。その後、部品に番号として簡単にアクセスできます。exp のオフセットを追加し、仮数の先頭に 1 を追加することを忘れないでください。

于 2010-10-03T19:12:26.383 に答える
0

あなたはごまかすことができ、frexpを使用するだけです。

于 2010-10-03T18:13:18.937 に答える
0
#include <iostream>

//float:1:8:23, bias 127
typedef union {
    float f;
    unsigned int ui;
    unsigned char c[4];
} Fl_u;
/*    
bool isLittleEndian(){
    Fl_u x;
    x.f = -0.0;
    return x.c[3] == 0x80;
}
*/
void fbinprint(float f){
    Fl_u x;
    unsigned wk=0;
    x.f = f;
/*  if(isLittleEndian())
        for(int i=3;i>=0;--i)
            wk = (wk << 8) + x.c[i];
    else
*/      wk = x.ui;
    if(wk & 0x80000000)
        std::cout << '-';
    unsigned bit = wk & 0x07FFFFF;
    std::cout << "1.";
    for(int i = 0; i< 23 ; ++i){
        bit <<=1;
        std::cout << (bit & 0x0800000 ? '1' : '0');
    }
    std::cout << " E";
    int exp = (wk >> 23) & 0x0FF;
    exp -= 127;//bias 127
    if(exp < 0){
        std::cout << '-';
        exp = -exp;
    }
    int i = 0;
    while((exp & 0x080) == 0 && i < 8){//skip zero of top
        exp <<= 1;
        ++i;
    }
    if(i == 8)
        std::cout << '0';
    for(;i< 8 ; ++i){
        std::cout << (exp & 0x080 ? '1' : '0');
        exp <<=1;
    }
    std::cout << std::endl;
}

int main(){
    float f = -40.1;
    std::cout << "Input: " << f << std::endl;
    std::cout << "Output: ";
    fbinprint(f);
    std::cout << std::endl;
    f = 13.5;
    std::cout << "Input: " << f << std::endl;
    std::cout << "Output: ";
    fbinprint(f);
//  fbinprint(0.0625);
}
于 2012-05-10T20:35:56.010 に答える