C++ 中浮点到基数 2 科学计数法(IEEE 32 位)的算法或代码?

发布于 2024-09-26 02:03:23 字数 461 浏览 2 评论 0原文

我将浮点数作为输入,然后以 2 进制科学记数法输出其等效表示形式。这是 IEEE 32 位,具有:31 个符号位、23-30 指数(具有 127 偏移量)、0-22 尾数(具有隐式前导 1)。

我不太确定其含义的条件之一是“您的尾数应该在前面添加隐式前导 1”。

我真正学到的只是将浮点数分解为小数部分和小数部分,并分别获取它们的二进制表示形式。

因为我不确定如何做到这一点...我无法真正编写代码。我很感激有关某种算法或代码本身的任何提示或信息。谢谢。

示例:

Input: -40.1
Output: -1.01000000110011001100110 E101

Input: 13.5
Output: 1.10110000000000000000000 E11

编辑:127 偏移量意味着超过 127 符号,对吗?我的书只有128多,但我不知道有什么区别......

I'm taking in a float as input, and then outputting its equivalent representation in base 2 scientific notation. This is in IEEE 32 bits with: 31 sign bit, 23-30 exponent (with 127 offset), 0-22 mantissa (with implicit leading 1).

One of the conditions which I'm not exactly sure the meaning of is "Your mantissa should have the implicit leading 1 prepended."

All I've really learned is to break up the float into its decimal and fractional parts, and separately get their binary representations.

Since I'm not sure how to do this... I can't really code it. I'd appreciate any tips or information on some sort of algorithm for doing so, or the code itself. Thanks.

Sample:

Input: -40.1
Output: -1.01000000110011001100110 E101

Input: 13.5
Output: 1.10110000000000000000000 E11

EDIT: 127 offset means excess 127 notation right? My book only has excess 128, but I don't know the difference anyways...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

假装不在乎 2024-10-03 02:03:23

所以我不会为你做所有的工作,因为这听起来像是家庭作业。但我会让你开始,你可以填补空白。因此,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;
}

您剩下要做的就是提取尾数和指数。您可以运行例程一次以生成尾数,然后再次运行以生成指数。我将简要解释如何执行这两项操作以及需要注意的事项。

生成尾数时,请记住 IEEE 使用隐藏的 1 和保留的零代码,因此总会有一个额外的 1 不在位表示中。本质上,您将检查符号位打印 - 或 + 取决于它,然后 1. 然后跳到尾数并打印后面的内容。然后你会回到 23-30 位,你想将其转换为 int,将每个位乘以 2^i(23 位是 0,24 位是 1,等等),然后你会想要从 int 中减去偏移量。然后使用前面的大纲方法输出指数的二进制表示形式,我会考虑在达到 1 之前不输出。希望这会有所帮助。

So I'm not going to do quite all of the work for you, because this sounds like homework. But I'll get you started and you can fill in the gaps. So there's a handy data type in c++ that's called a union, with it you can have multiple data types take up the same space. This is very useful, if say you want to see the bit representation of a floating point number. The following code will output the binary representation of a floating point number:

#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;
}

All that's left for you to do is extract the mantissa and the exponent. You could run the routine once to generate the mantissa and again to generate the exponent. I'll give a brief explanation of how to do both and things to watch out for.

When generating the mantissa remember that IEEE uses a hidden 1 with a reserved code for zero, so there's always going to be an extra one that isn't in the bit representation. Essentially you'll check the sign bit print - or + depending on it, then 1. then skip to the mantissa and print what follows. Then you'll go back to the 23-30 bits, you want to convert it to an int, to do this multiply each bit by 2^i (23 bit is 0, 24 bit is 1, etc) and then you'll want to subtract the offset from the int. Then using the previously outline method output the binary representation of the exponent, I would consider not outputting until you hit a 1. Hope this helps.

梦醒时光 2024-10-03 02:03:23

你可以作弊,只需使用 frexp 即可。

You can cheat, and just use frexp.

离去的眼神 2024-10-03 02:03:23

最简洁的方法之一是使用位掩码。也许更好的方法是使用位域。您可以定义一个结构来表示浮点格式:

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

然后获取浮点数,并将其转换为该结构:

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

这会重新解释数据位而不更改它们。然后您可以轻松地以数字形式访问零件。只需记住添加 exp 的偏移量并添加尾数的前导 1 即可。

One of the cleanest ways to do this is with bitmasking. Perhaps a better way is with bitfields. You can define a struct to represent the floating point format:

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

Then get your float, and cast it to this struct:

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

This reinterprets the bits of data without changing them. Then you can easily access the parts as numbers. Just remember to add the offset for exp and add the leading 1 for the mantissa.

任谁 2024-10-03 02:03:23
#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);
}
#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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文