浮点数转换为十进制数

题目:将32位浮点数 01000010111011010000000000000000 转换为十进制格式


根据国际标准IEEE 754,任意一个二进制浮点数V可以表示成下面的形式:

(1)(-1)^s表示符号位,当s=0,V为正数;当s=1,V为负数。

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

(3)2^E表示指数位。

IEEE754标准中规定float单精度浮点数在机器中表示用 1 位表示数字的符号,用 8 位来表示指数,用23 位来表示尾数,即小数部分。对于double双精度浮点数,用 1 位表示符号,用 11 位表示指数,52 位表示尾数,其中指数域称为阶码。
题目中的32位浮点数,可以写为 S+E+M 三部分的形式:0 10000101 11011010000000000000000

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

IEEE 754对有效数字M和指数E,还有一些特别规定。

  • 有效数字 M ,1≤M<2,也就是说,M可以写成1.xxxxxx的形式,其中xxxxxx表示小数部分。IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。
  • 至于指数E,首先,E为一个无符号整数(unsigned int)。这意味着,如果E为8位,它的取值范围为0-255;如果E为11位,它的取值范围为0-2047。但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,E的真实值必须再减去一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。

指数E还可以再分成三种情况:

E不全为0或不全为1。

这时,浮点数就采用上面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。

E全为0。

这时,浮点数的指数E等于1-127(或者1-1023),有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。

E全为1。

这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);如果有效数字M不全为0,表示这个数不是一个数(NaN)。

举例来说,

十进制的5.0,写成二进制是101.0,相当于1.01×2^2。那么,按照上面V的格式,可以得出s=0,M=1.01,E=2。

十进制的-5.0,写成二进制是-101.0,相当于-1.01×2^2。那么,s=1,M=1.01,E=2。

public static void main(String[] args){
        String binaryString="01000010111011010000000000000000";
        double result;  //存放结果
        String sign = binaryString.substring(0, 1); //得到符号位
        String exponent = binaryString.substring( 1, 9 );   //得到阶码
        int expint = Integer.parseInt(exponent, 2);     //指数转换为十进制
        int mobit = expint - 127;   //得到实际的阶码
        Double d = Math.pow(2,mobit);   //以2为底求值
        System.out.println(d);
        String last = binaryString.substring(9);    //得到尾数
        System.out.println(last);
        double lastRes = 0D;    //存放尾数的结果
        for(int i=0; i<last.length(); i++) {
            char b = last.charAt(i);
            if(b == '1') {
                lastRes += Math.pow(2, -(i + 1));   //尾数的计算
            }
        }
        result = d * (sign.equals("1") ? -1 : 1) * (1 + lastRes);
        System.out.println(result);
    }

JS 中的最大安全整数是多少?

JS 中所有的数字类型,实际存储都是通过 8 字节 double 浮点型 表示的。浮点数并不是能够精确表示范围内的所有数的, 虽然 double 浮点型的范围看上去很大: 2.23x10^(-308) ~ 1.79x10^308。 可以表示的最大整数可以很大,但能够精确表示,使用算数运算的并没有这么大。

它其实连这样的简单加法也会算错:

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

所以在 js 中能够安全使用的有符号 安全 大整数(注意这里是指能够安全使用,进行算数运算的范围),并不像其他语言在 64 位环境中那样是:

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

通过下面的例子,你会明白为什么大于这个值的运算是不安全的:

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

这些运算都是错误的结果, 因为它们进行的都是浮点数运算会丢失精度。

为什么是这个值?

double 浮点数结构如下:

1 位符号位
11 位指数位
52 位尾数位

使用 52 位表示一个数的整数部分,那么最大可以精确表示的数应该是 2^52 - 1 才对, 就像 64 位表示整数时那样: 2^63 - 1 (去掉 1 位符号位)。 但其实浮点数在保存数字的时候做了规格化处理,以 10 进制为例:

20*10^2 => 2*10^3 //小数点前只需要保留 1 位数

对于二进制来说, 小数点前保留一位, 规格化后始终是 1.***, 节省了 1 bit,这个 1 并不需要保存。

解决浮点数溢出的办法

  1. 使用toFixed方法返回一个以定点表示法表示的数字的字符串形式


  2. 调用一个处理函数
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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容