浮點(diǎn)數(shù)轉(zhuǎn)換為十進(jìn)制數(shù)

題目:將32位浮點(diǎn)數(shù) 01000010111011010000000000000000 轉(zhuǎn)換為十進(jìn)制格式


根據(jù)國(guó)際標(biāo)準(zhǔn)IEEE 754,任意一個(gè)二進(jìn)制浮點(diǎn)數(shù)V可以表示成下面的形式:

(1)(-1)^s表示符號(hào)位,當(dāng)s=0,V為正數(shù);當(dāng)s=1,V為負(fù)數(shù)。

(2)M表示有效數(shù)字,大于等于1,小于2。

(3)2^E表示指數(shù)位。

IEEE754標(biāo)準(zhǔn)中規(guī)定float單精度浮點(diǎn)數(shù)在機(jī)器中表示用 1 位表示數(shù)字的符號(hào),用 8 位來(lái)表示指數(shù),用23 位來(lái)表示尾數(shù),即小數(shù)部分。對(duì)于double雙精度浮點(diǎn)數(shù),用 1 位表示符號(hào),用 11 位表示指數(shù),52 位表示尾數(shù),其中指數(shù)域稱為階碼。
題目中的32位浮點(diǎn)數(shù),可以寫為 S+E+M 三部分的形式:0 10000101 11011010000000000000000

F87AF9B3-96A6-4892-BBD7-107968F22B5B.png

IEEE 754對(duì)有效數(shù)字M和指數(shù)E,還有一些特別規(guī)定。

  • 有效數(shù)字 M ,1≤M<2,也就是說(shuō),M可以寫成1.xxxxxx的形式,其中xxxxxx表示小數(shù)部分。IEEE 754規(guī)定,在計(jì)算機(jī)內(nèi)部保存M時(shí),默認(rèn)這個(gè)數(shù)的第一位總是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的時(shí)候,只保存01,等到讀取的時(shí)候,再把第一位的1加上去。這樣做的目的,是節(jié)省1位有效數(shù)字。以32位浮點(diǎn)數(shù)為例,留給M只有23位,將第一位的1舍去以后,等于可以保存24位有效數(shù)字。
  • 至于指數(shù)E,首先,E為一個(gè)無(wú)符號(hào)整數(shù)(unsigned int)。這意味著,如果E為8位,它的取值范圍為0-255;如果E為11位,它的取值范圍為0-2047。但是,我們知道,科學(xué)計(jì)數(shù)法中的E是可以出現(xiàn)負(fù)數(shù)的,所以IEEE 754規(guī)定,E的真實(shí)值必須再減去一個(gè)中間數(shù),對(duì)于8位的E,這個(gè)中間數(shù)是127;對(duì)于11位的E,這個(gè)中間數(shù)是1023。

指數(shù)E還可以再分成三種情況:

E不全為0或不全為1。

這時(shí),浮點(diǎn)數(shù)就采用上面的規(guī)則表示,即指數(shù)E的計(jì)算值減去127(或1023),得到真實(shí)值,再將有效數(shù)字M前加上第一位的1。

E全為0。

這時(shí),浮點(diǎn)數(shù)的指數(shù)E等于1-127(或者1-1023),有效數(shù)字M不再加上第一位的1,而是還原為0.xxxxxx的小數(shù)。這樣做是為了表示±0,以及接近于0的很小的數(shù)字。

E全為1。

這時(shí),如果有效數(shù)字M全為0,表示±無(wú)窮大(正負(fù)取決于符號(hào)位s);如果有效數(shù)字M不全為0,表示這個(gè)數(shù)不是一個(gè)數(shù)(NaN)。

舉例來(lái)說(shuō),

十進(jìn)制的5.0,寫成二進(jìn)制是101.0,相當(dāng)于1.01×2^2。那么,按照上面V的格式,可以得出s=0,M=1.01,E=2。

十進(jìn)制的-5.0,寫成二進(jìn)制是-101.0,相當(dāng)于-1.01×2^2。那么,s=1,M=1.01,E=2。

public static void main(String[] args){
        String binaryString="01000010111011010000000000000000";
        double result;  //存放結(jié)果
        String sign = binaryString.substring(0, 1); //得到符號(hào)位
        String exponent = binaryString.substring( 1, 9 );   //得到階碼
        int expint = Integer.parseInt(exponent, 2);     //指數(shù)轉(zhuǎn)換為十進(jìn)制
        int mobit = expint - 127;   //得到實(shí)際的階碼
        Double d = Math.pow(2,mobit);   //以2為底求值
        System.out.println(d);
        String last = binaryString.substring(9);    //得到尾數(shù)
        System.out.println(last);
        double lastRes = 0D;    //存放尾數(shù)的結(jié)果
        for(int i=0; i<last.length(); i++) {
            char b = last.charAt(i);
            if(b == '1') {
                lastRes += Math.pow(2, -(i + 1));   //尾數(shù)的計(jì)算
            }
        }
        result = d * (sign.equals("1") ? -1 : 1) * (1 + lastRes);
        System.out.println(result);
    }

JS 中的最大安全整數(shù)是多少?

JS 中所有的數(shù)字類型,實(shí)際存儲(chǔ)都是通過(guò) 8 字節(jié) double 浮點(diǎn)型 表示的。浮點(diǎn)數(shù)并不是能夠精確表示范圍內(nèi)的所有數(shù)的, 雖然 double 浮點(diǎn)型的范圍看上去很大: 2.23x10^(-308) ~ 1.79x10^308。 可以表示的最大整數(shù)可以很大,但能夠精確表示,使用算數(shù)運(yùn)算的并沒(méi)有這么大。

它其實(shí)連這樣的簡(jiǎn)單加法也會(huì)算錯(cuò):

console.log(0.1 + 0.2)
//output: 0.30000000000000004

所以在 js 中能夠安全使用的有符號(hào) 安全 大整數(shù)(注意這里是指能夠安全使用,進(jìn)行算數(shù)運(yùn)算的范圍),并不像其他語(yǔ)言在 64 位環(huán)境中那樣是:

2^63 - 1;//9223372036854775807

而是

Math.pow(2, 53) - 1     // 9007199254740991

JS 的最大和最小安全值可以這樣獲得:

console.log(Number.MAX_SAFE_INTEGER); //9007199254740991
console.log(Number.MIN_SAFE_INTEGER); //-9007199254740991

通過(guò)下面的例子,你會(huì)明白為什么大于這個(gè)值的運(yùn)算是不安全的:

var x = 9223372036854775807;
console.log(x === x + 1);// output: true
console.log(9223372036854775807 + 1000); //output: 9223372036854776000

這些運(yùn)算都是錯(cuò)誤的結(jié)果, 因?yàn)樗鼈冞M(jìn)行的都是浮點(diǎn)數(shù)運(yùn)算會(huì)丟失精度。

為什么是這個(gè)值?

double 浮點(diǎn)數(shù)結(jié)構(gòu)如下:

1 位符號(hào)位
11 位指數(shù)位
52 位尾數(shù)位

使用 52 位表示一個(gè)數(shù)的整數(shù)部分,那么最大可以精確表示的數(shù)應(yīng)該是 2^52 - 1 才對(duì), 就像 64 位表示整數(shù)時(shí)那樣: 2^63 - 1 (去掉 1 位符號(hào)位)。 但其實(shí)浮點(diǎn)數(shù)在保存數(shù)字的時(shí)候做了規(guī)格化處理,以 10 進(jìn)制為例:

20*10^2 => 2*10^3 //小數(shù)點(diǎn)前只需要保留 1 位數(shù)

對(duì)于二進(jìn)制來(lái)說(shuō), 小數(shù)點(diǎn)前保留一位, 規(guī)格化后始終是 1.***, 節(jié)省了 1 bit,這個(gè) 1 并不需要保存。

解決浮點(diǎn)數(shù)溢出的辦法

  1. 使用toFixed方法返回一個(gè)以定點(diǎn)表示法表示的數(shù)字的字符串形式


  2. 調(diào)用一個(gè)處理函數(shù)
function overflow(a, h, b) {
        var _a = a.toString().split(".");
        if (_a.length == 1) {
            _a = 0;
        } else {
            _a = _a[1].length;
        }
        var _b = b.toString().split(".");
        if (_b.length == 1) {
            _b = 0;
        } else {
            _b = _b[1].length;
        }
        if (_b > _a)_a = _b;
        _b = "1";
        for (; _a > 0; _a--) {
            _b = _b + "0";
        }
        switch (h) {
            case"+":
                return (a * _b + b * _b) / _b;
                break;
            case"-":
                return (a * _b - b * _b) / _b;
                break;
            case"*":
                return ((a * _b) * (b * _b)) / (_b * _b);
                break;
            default:
                return 0;
        }
    }

var a = 0.1;
var b = 0.2;
console.log(overflow(a, "+", b));//0.3

參考文章:http://www.ruanyifeng.com/blog/2010/06/ieee_floating-point_representation.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容