1. 程式人生 > >算法習題---3.12浮點數(UVa11809)

算法習題---3.12浮點數(UVa11809)

所有 out 範圍 open style con 32位 保存 stdin

一:題目

尷尬的非會員水印

技術分享圖片

二:題目摘要

1.int和float比較

int共32位,可以表示的最大的數為2^32次方
float雖然也是32位,但是是以指數形式保存,指數占8位(含符號),最大127,則表示最大數為2^127,可以表示到10^38次方數

2.float在內存中存在形式

技術分享圖片

其中尾數部分,默認前面省略了一個1

3.輸入數據的範圍

9.205357638345294e18
5.699141892149156e76  -->不能單純用float表示
0e0
double類型指數占11位,最高可以表示到10^308次方,可以滿足輸入條件

三:解題思路

(一)整數部分除2,小數部分乘2

例如:19.625

整數

19/2 = 9...1
9/2=4...1
4/2=2...0
2/2=1...0
1/2=0...1
19 = 10011

小數

0.625*2 = 1.25   -->  1
0.25*2 = 0.5  -->  0
0.5*2 = 1.0 -->  1
0.625 = 0.101

(二)位數確定(2^10=1024)>10^3>(2^9=512)

Xe18位數範圍為18/3*9到(18/3+1)*10之間--->其中18/3+1中+1是為了防止X帶來的誤差(例如X=8就是2^3,所以我們不妨直接將其擴大10位,即1*10)

(三)函數pow的參數是double類型,返回也是double類型

(四)為了在處理小數時方便計算,將double類型轉float(兩種保留位數不同,float位數較少)

四:數據展示

9.205357638345294e18
5.699141892149156e76
0e0
8 6
5 8

五:代碼分析

(一)獲取指數值

        bit = 0;
        while (temp>1)
        {
            temp /= 10;
            bit++;
        }
        bit
--;   //bit是整數位數(1000.1就是bit=3)
        for (bin_bit = bit / 3 * 9; bin_bit <= (bit / 3 + 1) * 10; bin_bit++)
        {
            if ((num / pow(2.0, bin_bit)) < 1)
                break;
        }
其中num是我們獲取的需要處理的最大浮點數
bin_bit是根據三(二)中確定的值,循環次數從bit/3*9到(bit/3+1)*9,
當num/pow(2.0,bin_bit)小於1時,就是處理了所有的的指數值

(二)根據指數值,獲取尾數值

        //指數是bin_bit位
        //尾數是num / pow(2.0, bin_bit)
        mant_val = num / pow(2.0, bin_bit);    //double轉float只是為了保留15位小數,方便後面比較運算
        expo_val = bin_bit;

(三)根據三(一)獲取指數值位數

        while (expo_val)
        {
            expo++;  //初始為0
            expo_val /= 2;
        }

(四)根據小數運算獲取小數位數

        while (mant_val>1e-15)  //因為float有效位數15位
        {
            if (mant_val * 2 >= 1.0)
                mant_val = mant_val*2 - 1;
            else
                mant_val = mant_val * 2;

            mant++;
        }

    
mant--; //因為有一個1被默認省略,所以減去

六:代碼實現

//浮點數求尾數和指數位數
//整數部分除2,小數部分乘2
void test37()
{
    double num, temp;    //考慮位數,取double類型
    int bit,bin_bit;
    float mant_val;    //尾數值
    int expo_val;    //指數值
    int mant, expo;  //尾數位數和指數位數
    freopen("data.in", "r", stdin);
    freopen("data.out", "w", stdout);

    while (1)
    {
        scanf("%lf", &num);  //註意:double類型讀取時,使用lf
        expo = mant = 0;

        temp = num;    
        if (temp == 0)
            break;

        bit = 0;
        while (temp>1)
        {
            temp /= 10;
            bit++;
        }
        bit--; 

        for (bin_bit = bit / 3 * 9; bin_bit <= (bit / 3 + 1) * 10; bin_bit++)
        {
            if ((num / pow(2.0, bin_bit)) < 1)
                break;
        }
        //指數是bin_bit位
        //尾數是num / pow(2.0, bin_bit)
        mant_val = num / pow(2.0, bin_bit);    //double轉float只是為了保留15位小數,方便後面比較運算
        expo_val = bin_bit;

        while (expo_val)
        {
            expo++;
            expo_val /= 2;
        }

        while (mant_val>1e-15)
        {
            if (mant_val * 2 >= 1.0)
                mant_val = mant_val*2 - 1;
            else
                mant_val = mant_val * 2;

            mant++;
        }

        mant--;    //因為有一個1被默認省略,所以減去
        
        printf("%d %d\n", mant, expo);
    }

    freopen("CON", "r", stdin);
    freopen("CON", "w", stdout);
}

算法習題---3.12浮點數(UVa11809)