javascript 数字处理

·  阅读 1769

数字处理

常见的数字类型

JavaScript 不区分整数和浮点数,统一用 Number  表示数字类型,常见的数字类型如下

// 以下使用 typeof 判断结果均为 number
typeof(96) // 整数
typeof(3.1415926) // 浮点数
typeof(1.23e456) // 科学计数法
typeof(0x123) // 十六进制
typeof(-1) // 负数
typeof(NaN) // 非数字 非正常数字表示或者 无法计算出结果的时候
typeof(Infinity) // 正无穷大 与之对应 -Infinity 是负无穷大
复制代码

如何判断一个数是数字

typeof && isNaN && isFinite

一般而言判断数字我理解为可以进行计算的数字,那么需要排除 NaN 和 Infinity 的干扰。这里有一个函数,可以巧妙的过滤 NaN 和 Infinity 
使用 isFinite 判定一个数字是否是有限数字。isFinite 方法检测它参数的数值。如果参数是 NaN,正无穷大或者负无穷大,会返回false,其他返回 true
如果只需要区分 NaN 使用 isNaN 就行。

/**
* testValue 检测有限性的值 入参
*/
isFinite(testValue)
复制代码

最终的判断函数

function isNumber(target) {
  return typeof target === 'number' && isFinite(target)
}
复制代码

Object.prototype.toString.call

Object.prototype.toString.call 也是一种判断数据类型的比较常见的方法,在判断数字的时候可以用它替换 typeof

function isNumber(target) {
  return Object.prototype.toString.call(target) === '[object Number]' && isFinite(target)
}
复制代码

+

这是一个比较巧妙的方法,在需要判断的对象前面添加一个 + ,这样就转换为number类型,如果与自身相等则表示这个对象是一个数字。有个缺陷是判断 Infinity 的时候还是返回 true ,不过问题不大。

function isNumber(target) {
  return target === +target
}
复制代码

这个方法也可以用于检测字符类型和布尔类型

function isString(target) {
  return target === target+''
}
function isBollean(target) {
  return target === !!target
}
复制代码

正则

通过正则去判断,这里没有考虑科学计数法和一些其他进制的表示方式,而且没有数字字符 '123' 也会被任务是数字。

function isNumber(obj) {
  var reg = /^[0-9]+.?[0-9]*$/
  return reg.test(obj)
}
复制代码

个人建议还是使用第一种方式来进行数字的判断
**

格式化

取整

parseInt(3/2) // 1
复制代码

这里需要注意 parseInt 的参数。

**parseInt(stringradix)  ** 将一个字符串 string 转换为 radix 进制的整数, radix 为介于2-36之间的数。

详细的分析可以参考developer.mozilla.org/zh-CN/docs/…
这里会有一个坑,就是在上机编程的时候有时候会使用如下的方式将输入转换成数字

输入
1 2 3 4
输出
最大值:4

程序
inputs = readline().split(' ').map(parseInt) // 输入转数字数组
console.log(Math.max(...inputs)) // 输出最大值
复制代码

如果直接按照上述方式进行计算,会发现之后的计算都是 NaN 。主要是 map 函数的参数传入的处理函数的参数顺序是 item index array 这时候结合 parseInt 的参数,会发现

  1. parseInt('1', 0) //radix为0时,且string参数不以“0x”和“0”开头时,按照10为基数处理。这个时候返回1
  2. parseInt('2', 1) //基数为1(1进制)表示的数中,最大值小于2,所以无法解析,返回NaN
  3. parseInt('3', 2) //基数为2(2进制)表示的数中,最大值小于3,所以无法解析,返回NaN
var num = '1 2 3 4'.split(' ').map(parseInt)
console.log(num)
// [1, NaN, NaN, NaN]
复制代码

这里有各路大佬的讨论 github.com/Advanced-Fr…

四舍五入

Math.round(5/3) // 2
复制代码

向上取整

 Math.ceil(5/3) // 2
复制代码

向下取整

Math.floor(5/3) // 1
复制代码

保留小数点后N位

  • **toFixed() **方法可以将数字转换为字符串,并指定小数点后保留几位。如果小数实际位数不够指定的位数,不足的部分会补 0
  • toFixed() 使用的是银行家舍入规则:四舍六入五取偶(又称四舍六入五留双)。

银行家舍入法: 四舍六入五考虑,五后非零就进一,五后为零看奇偶,五前为偶应舍去,五前为奇要进一。

var num1 = (5/3).toFixed(2);  // 1.67
var num2 = (4).toFixed(2);  // 4.00
var num3 = (0.015).toFixed(2);  // 0.01
var num4 = (0.025).toFixed(2);  // 0.03
复制代码

自定义保留小数点后N位

上述方法使用的舍入方法是银行家舍入法与传统上的四舍五入保留小数还不一致,下面有一个小的demo来改进,尝试之后一般情况下都是可以
思路:

  1. 放大需要保留小数位数的 10^n
  2. 四舍五入
  3. 然后在缩小相同的倍数

1/ 3 0.33333333 保留两位小数 0.33333 * 100 = 33.333 四舍五入 33 缩小相同倍数 0.33

function selfRound(target, num) {
  return Math.round(target*Math.pow(10,num)) / Math.pow(10,num)
}
复制代码

上述的对于整数,后面不会补全0,下面改进

//保留n位小数并格式化输出(不足的部分补0)
var fomatFloat = function(value, n) {
    var f = Math.round(value*Math.pow(10,n))/Math.pow(10,n)
    var s = f.toString();
    var rs = s.indexOf('.')  
    if (rs < 0) {     
        s += '.'
    } 
    for(var i = s.length - s.indexOf('.'); i <= n; i++){
      s += "0"
    }
    return s
}
复制代码
分类:
阅读
标签:
分类:
阅读
标签:
收藏成功!
已添加到「」, 点击更改