整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

关于JavaScript小数点取整数函数

关于JavaScript小数点取整数函数

.丢弃小数部分,保留整数部分

parseInt(5/2)

2.向上取整,有小数就整数部分加1

Math.ceil(5/2)

3,四舍五入.

Math.round(5/2)

4,向下取整

Math.floor(5/2)

责声明:

我已经尽量简化了,由于观看本节内容导致的头晕、脱发、恶心、呕吐等生理症状,本人概不负责

在现实世界中,小数的书写方式非常自然,只需要使用.即可代表之后的数字全是小数,例如3.1415926

但是计算机存储小数的时候,麻烦就来了。

比如3.14,整数部分的二进制是11,小数部分的二进制是1011,合在一起就是111011,你能说这个数是3.14吗?

问题的根源就在它难以准确的表述小数点的位置。

因此,必须另寻他法。

浮点数基本概念

聪明的人想出了一个巧妙的办法

在现实世界中,任何数字都可以表示为a.xxxx * 10^na.xxxx?10n,其中,a的取值范围是1~9

这叫做科学计数法

比如:

1024.5678=1.0245678 * 10^31024.5678=1.0245678?103,它表示,1.0245678的小数点向右移动3位,即最终的十进制小数

952.7=9.527 * 10^2952.7=9.527?102,它表示,9.527的小数点向右移动2位,即最终的十进制小数

那二进制是否也可以这样表示呢?

当然可以,在二进制的世界中,任何数字(包括整数)都可以表示为a.xxxx * 2^na.xxxx?2n,a只能取1

比如:

110.101=1.10101 * 2^2110.101=1.10101?22,它表示,1.10101的小数点向右移动2位,即最终的二进制小数

0010.00011=1.000011 * 2^10010.00011=1.000011?21,它表示,1.000011的小数点向右移动1位,即最终

的二进制小数

可以看出,二进制如果也使用科学计数法,以下东西都是固定的:

底数2

整数部分1

而不固定的部分是:

指数部分

尾数部分(小数点后面的部分)

因此,我们可以使用下面的方式来表示一个数字

第一部分第二部分第三部分

符号 阶码 尾数

0为正,1为负 这部分表示指数部分 这部分表示小数点后面的部分

这种表示数字的方法,叫做浮点数表示法

比如,110.101=1.10101 * 2^2110.101=1.10101?22,改数字的符号是0,阶码是2,阶码的二进制格式是10,尾数是10101,因此,在计算机中可以用浮点数表示为:

符号阶码尾数

0 10 10101

是不是很简单。

但这样一来,容易导致CPU搞不清楚阶码和尾数是在哪里分割的,我们可以轻松的从表格中看出,但计算机哪有什么表格,它是存在一起的:01010101

为了解决这个问题,阶码和尾数的长度就必须固定

比如,阶码的长度规定为3,尾数的长度规定为4,加上一个符号位,刚好是8位,一个字节

如果按照这种约定,计算机就可以轻松的取出第一个符号位,然后轻松的取出后三位阶码,继续取出后四位的尾数

符号(1)阶码(3)尾数(4)

0 010 1010

可以看到,这种情况下,尾数的最后一位被丢弃了,从10101变成了1010,因为它只能存储4位。

所以,使用浮点数存储数字时,可能导致存储的数字不精确

以上,就是浮点数存储数字的方式。

数字到浮点数的转换

我们知道,二进制科学计数法是浮点数的基石,只要有了二进制的科学计数法,就可以变成浮点数的存储了。

然而,我们平时接触更多的是十进制的小数

现在的问题是:如何把十进制的小数转换为浮点数的科学计数法?

下面将一步一步进行分析

二进制小数到十进制小数

要理解十进制小数是如何转换成二进制小数的,就必须要先理解相反的情况:二进制小数是如何转换成十进制小数的。

我们知道,任何一个十进制的小数(包括整数)都可以书写为下面的格式:

21.25=2 * 10^1 + 1 * 10^0 + 2 * 10^{-1} + 2 * 10^{-2}21.25=2?101+1?100+2?10?1+2?10?2

二进制的小数也可以用同样的规则,只不过把底数10换成底数2

下面的示例就是把一个二进制小数11.01转换成了十进制小数3.25:

11.01_2=1 * 2^1 + 1 * 2^0 + 0 * 2^{-1} + 1 * 2^{-2}=3.25_{10}11.012=1?21+1?20+0?2?1+1?2?2=3.2510

十进制小数到二进制小数

知道了二进制小数转十进制,反过来也是一样的

省略了具体的数学推导(数学好的朋友自行完成),我们按照下面的方式来转换

比如十进制数3.25

首先转换整数部分:

3_{10}=11310=11

整数部分的转换在之前的章节已经说的很详细了,不再重复

然后转换小数部分

现有小数乘以2取整数部分

0.25 0.5 0

0.5 1 1

0 不再处理 不再处理

最终得到的二进制小数部分是01,即把每次取整部分从上到下依次罗列即可

0.25_{10}=0.01_20.2510=0.012

把最终的整数部分加入进去,就形成了

3.25_{10}=11.01_{2}3.2510=11.012

无法精确转换

有的时候,这种转换是无法做到精确的

比如0.3这个十进制数,转换成二进制小数按照下面的过程进行

现有小数乘以2取整数部分

0.3 0.6 0

0.6 1.2 1

0.2 0.4 0

0.4 0.8 0

0.8 1.6 1

0.6 1.2 1

0.2 0.4 0

0.4 0.8 0

0.8 1.6 1

0.6 1.2 1

... ... ...

0.3_{10}=0.0 1001 1001 1001 1001 ...=0.0\overline{1001}0.310=0.01001100110011001...=0.01

在转换的过程中,可能导致十进制的现有小数永远无法归零,于是转换成了一个无限的二进制小数。

同时,计算机无法存储一个无限的数据,因此,总有一些数据会被丢弃,这就造成了计算机存储的小数部分可能是不精确的

进一步,如果一个小数无法精确的存储,那么他们之间的运算结果也是不精确的

这就是计算机对小数的运算不精确的原因

// js语言中运行5.3 - 5.2 // 得到0.09999999999999964

转换成二进制的科学计数

现在,按照以上所述的规则,我们已经可以轻松的把一个十进制的数字转换成二进制格式了

然后,我们再在它的基础上,把它变化为二进制的科学计数格式

3.25_{10}=11.01_2=1.101 * 2^13.2510=11.012=1.101?21

注意,1.101 * 2^11.101?21是二进制的科学计数表示,你并不能把它当成十进制的方式运算,如果你要将其转换成十进制,应该:

将1.101的小数点向右移动1位,得到11.01

.01=1

2^1 + 1

2^0 + 0

2^{-1} + 1

2^{-2}=3.25$

当我们拿到这个数的二进制科学计数后,就可以轻松的将其存储下来了

3.25=11.01=1.101 * 2^1=1.1010 * 2^13.25=11.01=1.101?21=1.1010?21的存储

因为尾数是4位,所以不足在后面补0

符号(1)阶码(3)尾数(4)

0 001 1010

然而

请允许我做一个悲伤的表情

还有一种情况没有考虑到...

指数偏移量

建议先读完本节内容,然后再反复推理和思考

我们来聊一聊还有什么情况没有考虑到

现在,我们有一个十进制的数字0.25,它转换成二进制的格式应该是0.01,科学计数法表示的结果是1*2^{-2}1?2?2,即小数点应该向左移动2位

现在的问题是,指数部分出现了负数!

注意,不是数字是负数,是指数是负数

问题在于,我难道对指数也要使用一个符号位来处理负数的情况吗?

实际上没有必要,在计算机运算浮点数时,对于指数部分,更多的操作是比较,即比较两个指数哪个大

如果使用符号位的话,在比较时就必须考虑符号的问题,这样会给比较带来很多麻烦

因此,IEEE 754规定,使用指数偏移量来处理这个问题

IEEE 754是对浮点数存储、运算的国际标准,绝大部分计算机语言的浮点数都遵循该标准

它规定,如果一个浮点数的指数位数为ee,则它的指数偏移量为2^{e - 1} - 12e?1?1,不管存储什么指数值,都需要加上这个偏移量后再进行存储。

比如,指数的位数是3,则指数的偏移量为2^{3-1} - 1=323?1?1=3,当存储指数-2时,需要加上偏移量3再进行存储,因此,指数-2实际上存储的是1,即001

再比如,当存储指数2时,需要加上偏移量3再进行存储,因此,指数2实际上存储的是5,即101

如果比较-2和2哪个大,就直接比较两个二进制即可,001显然比101要小,指数部分完全没有符号位,这样比较起来就轻松多了。

当然,当需要还原它的真实指数时,只需要减去偏移量即可

于是,有了这样的规则后:

0.25_{10}=0.01_2=1.0000 * 2^{-2}0.2510=0.012=1.0000?2?2

符号(1)阶码(3)尾数(4)

0 001 0000

3.25_{10}=11.01_2=1.1010 * 2^13.2510=11.012=1.1010?21

符号(1)阶码(3)尾数(4)

0 100 1010

由于有了偏移量的存在,浮点数的指数范围就可以很轻松的算出来了

最小能存储的指数是000,减去偏移量后真实的指数是-3

最大能存储的指数是111,减去偏移量后真实的指数是4

稍微的总结一下,就是:

阶码为n位的浮点数,指数的真实范围是-2^{n-1}+1?2n?1+1 到 2^{n-1}2n?1

特殊值

在浮点数的标准中,有下面两个特殊值:

NaN:Not a Number,表示不是一个数字,它通常来自一些错误的运算,比如

3.14 * "你好"

Infinity:正向的无穷大,相当于数学中的

\infty

-Infinity:负向的无穷大,相当于数学中的

-\infty

?

为了表示这三个值,IEEE 754标准规定,当使用一种特殊的数字存储来表示:

NaN

符号(1)阶码(3)尾数(4)

无所谓

比如:

符号(1)阶码(3)尾数(4)

0 111 1010

上面这个数字可不是1.1010*2^{4}1.1010?24,它是一个NaN

无穷

符号(1)阶码(3)尾数(4)

0:正无穷,1:负无穷 111

比如:

符号(1)阶码(3)尾数(4)

0 111 0000

上面这个数字可不是1.0000*2^{4}1.0000?24,它是一个Infinity

由于特殊值的存在,让阶码的最大值用于表示特殊值,因此,正常的数字阶码是不能取到最大值的

因此,正常数字的阶码取值范围少了一个:-2^{n-1}+1?2n?1+1 到 2^{n-1} - 12n?1?1

比如,3位的阶码,它能表示的正常指数范围是-3到3

单精度和双精度

很多计算机语言中都有单精度和双精度的概念,它们的区别在于阶码和尾数的位数是不一样的

Java的float是单精度浮点数,double是双精度浮点数

JS的所有数字均为双精度浮点数

类型符号阶码尾数共计

单精度 1位 8位 23位 32bit,4byte

双精度 1位 11位 52位 64bit,8byte

总结

由于浮点数这种特别的存储方式,因此,不同的阶码和尾数的位数,决定了:

阶码位数越多,可以取到的指数越大,因此可以表示的数字越大

尾数位数越多,可以表示的数字位数越多,因此可以表示的更加精确

习目总标

本次学习目标

1. JavaScript

1.1 JavaScript的起源

在1995年时,由Netscape公司的Brendan Eich,在网景导航者浏览器上首次设计实现而成。Netscape在最初将其脚本语言命名为LiveScript,因为Netscape与Sun合作,网景公司管理层希望蹭Java的热度,因此取名为JavaScript。

JavaScript总共分成三部分: ECMAScript(基本语法)、BOM(浏览器对象模型)、DOM(文档对象模型)

1.2 JavaScript的特性

1.2.1 脚本语言

JavaScript是一种解释型的脚本语言。不同于C、C++、Java等语言先编译后执行, JavaScript不会产生编译出来的字节码文件,而是在程序的运行过程中对源文件逐行进行解释。

1.2.2 基于对象

JavaScript是一种基于对象的脚本语言,它不仅可以创建对象,也能使用现有的对象。但是面向对象的三大特性:『封装』、『继承』、『多态』中,JavaScript能够实现封装,可以模拟继承,不支持多态,所以它不是一门面向对象的编程语言。

1.2.3 弱类型

JavaScript中也有明确的数据类型,但是声明一个变量后它可以接收任何类型的数据,并且会在程序执行过程中根据上下文自动转换类型。

1.2.4 事件驱动

JavaScript是一种采用事件驱动的脚本语言,它不需要经过Web服务器就可以对用户的输入做出响应。

1.2.5 跨平台性

JavaScript脚本语言不依赖于操作系统,仅需要浏览器的支持。因此一个JavaScript脚本在编写后可以带到任意机器上使用,前提是机器上的浏览器支持JavaScript脚本语言。目前JavaScript已被大多数的浏览器所支持。

1.3 HelloWorld

1.3.1 功能效果图

1.3.2 代码实现

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS的入门程序</title>
</head>
<body>
<!-- 在HTML代码中定义一个按钮 -->
<button type="button" id="helloBtn">SayHello</button>
<!--
目标: 点击按钮的时候弹出一个警告框
-->
<script type="text/javascript">
//1. 通过js代码获取到按钮对象
//document代表当前HTML文档
var btn=document.getElementById("helloBtn");
//2. 给获取到的btn对象绑定点击事件
btn.onclick=function () {
//弹出警告框
alert("hello world");
}