quiz
quiz copied to clipboard
JS基础测试33
一转眼又到周三了,本期小测题目如下,围绕toFixed()方法展开:
大家提交回答的时候,注意缩进距离,起始位置从左边缘开始;另外,github自带代码高亮,所以请使用下面示意的格式。
```js // 你的JS代码写在这里 ```
其它:
- 首位答题者可获得额外2积分和直播翻牌机会;
- 本次答疑直播为6月15日上午10:00,会和上期CSS小测一起答疑,大约40多分钟;
-
"1"
-
"2"
-
"0.04"
-
"0.04"
-
Number.prototype.toFixed=function(v){return (this>0?1:-1)*parseInt(Math.round(Math.abs(this) * Math.pow(10,v))) / Math.pow(10,v)}
-
String.prototype.toFixed=function(v){return (this>0?1:-1)*parseInt(Math.round(Math.abs(this) * Math.pow(10,v))) / Math.pow(10,v)}
//zxx: 1. 应该返回字符串;2. 应该补全末尾的0
Chrome | Firefox | IE11 | |
---|---|---|---|
0.6.toFixed(0) |
1 | 1 | 1 |
1.6.toFixed(0) |
2 | 2 | 2 |
0.035.toFixed(2) |
0.04 | 0.04 | 0.04 |
0.045.toFixed(2) |
0.04 | 0.04 | 0.05 |
Number.prototype.toFixed = myToFixed;
String.prototype.toFixed = myToFixed;
function myToFixed(digits = 0) {
let num = String(this);
// 小数位不足时后置补零
const postfixZero = s => {
let len = digits;
if (s.indexOf('.') > 0) {
len = digits - s.split('.')[1].length;
} else if (len > 0) {
s += '.'; // 整数位后补小数点
}
return s + '0'.repeat(len);
};
digits = parseInt(digits, 10);
if (isNaN(digits)) { // 非数值
throw new Error('digits argument must be a number(or string number)');
}
if (digits < 0) { // 负数
throw new Error('digits argument must be greater than or equal to 0');
}
if (!isFinite(num)) { // +-Infinity
return num;
}
if (num.indexOf('.') > 0) {
let times = Math.pow(10, digits); // 根据小数位长度获取升幂倍数
num = Math.round(num * times) / times + ''; // 四舍五入,降幂
}
return postfixZero(num);
}
测试用例:
console.group('普通场景测试');
console.log(0.6.toFixed(0)); // "1"
console.log(1.6.toFixed(0)); // "2"
console.log(0.035.toFixed(2)); // "0.04"
console.log(0.045.toFixed(2)); // "0.05"
console.groupEnd();
console.group('进阶场景测试');
console.log(Math.PI.toFixed(10)); // "3.1415926536"
console.log(0.9.toFixed()); // "1"
console.log(Number(5).toFixed(2)); // "5.00"
console.log(3..toFixed(3)); // "3.000"
console.log(.5.toFixed('3')); // "0.500"
console.log(1.2345.toFixed(2.6)); // "1.23"
console.groupEnd();
console.group('参数异常测试');
console.log(Infinity.toFixed(5)); // "Infinity"
console.log(0.5.toFixed(-2)); // Error: digits argument must be greater than or equal to 0
console.log(0.5.toFixed(null)); // Error: digits argument must be a number(or string number)
console.groupEnd();
//zxz: 滴~满分~
2019-07-21:无法通过
1.005.toFixed(2)
的测试用例,期望返回1.01
实际返回1.00
- 1
- 2
- 0.04
- 0.05
Number.prototype.toFixed = String.prototype.toFixed = function (number) {
if(isNaN(number)) return;
return parseInt(this * Math.pow(10, number) + 0.5) / Math.pow(10, number);
}
//zxx: 1. 应该返回字符串;2. 应该补全末尾的0
以谷歌浏览器作答
- 1
- 2
- 0.04
- 0.04
String.prototype.toFixed = Number.prototype.toFixed = function (fractionDigits) {
var num = this;
if(isNaN(num)){
throw Error(`${num}不是一个数字`);
}
return Math.round(num * Math.pow(10, fractionDigits)) / Math.pow(10, fractionDigits);
};
- '1'
- '2'
- '0.04'
- '0.04' (Chrome); '0.05' (IE)
Number.prototype.toFixed = function(d) {
d = isNaN(d) ? 0 : parseInt(d);
if (d < 0 || d > 20) {
throw new RangeError('toFixed() digits argument must be between 0 and 20');
}
var val = this.toString();
if (val.indexOf('.') < 0) {
return val;
}
if (d === 0) {
return val.replace(RegExp('^([0-9]+)(?:\\.)([0-9])[0-9]*$'), function(m,intPart, judgePart) {
return (+judgePart >= 5 ? ((+intPart + 1) + '') : intPart);
});
} else {
return val.replace(RegExp('^([0-9]+\\.)([0-9]*)$'), function(m, intPart, fractionalPart) {
return intPart + (fractionalPart.length < d ? (fractionalPart + Array(d - fractionalPart.length + 1).join('0')) : fractionalPart);
}).replace(RegExp('^([0-9]+)(\\.)([0-9]{' + d + '})([0-9])[0-9]*$'), function(m, intPart, dotPart, keepPart, judgePart) {
var orgLen = keepPart.length;
var newVal = (+judgePart >= 5 ? (+keepPart + 1) : +keepPart).toString();
if (newVal.length > orgLen) {
return (+intPart + (+newVal.slice(0,1))) + dotPart + newVal.slice(1);
} else if (newVal.length < orgLen) {
return intPart + dotPart + Array(orgLen - newVal.length + 1).join('0') + newVal;
} else {
return intPart + dotPart + newVal;
}
});
}
};
String.prototype.toFixed = function(d) {
if (isNaN(this)) {
return NaN;
}
d = isNaN(d) ? 0 : parseInt(d);
if (d < 0 || d > 20) {
throw new RangeError('toFixed() digits argument must be between 0 and 20');
}
var val = (+this).toString();
if (val.indexOf('.') < 0) {
return val;
}
if (d === 0) {
return val.replace(RegExp('^([0-9]+)(?:\\.)([0-9])[0-9]*$'), function(m,intPart, judgePart) {
return (+judgePart >= 5 ? ((+intPart + 1) + '') : intPart);
});
} else {
return val.replace(RegExp('^([0-9]+\\.)([0-9]*)$'), function(m, intPart, fractionalPart) {
return intPart + (fractionalPart.length < d ? (fractionalPart + Array(d - fractionalPart.length + 1).join('0')) : fractionalPart);
}).replace(RegExp('^([0-9]+)(\\.)([0-9]{' + d + '})([0-9])[0-9]*$'), function(m, intPart, dotPart, keepPart, judgePart) {
var orgLen = keepPart.length;
var newVal = (+judgePart >= 5 ? (+keepPart + 1) : +keepPart).toString();
if (newVal.length > orgLen) {
return (+intPart + (+newVal.slice(0,1))) + dotPart + newVal.slice(1);
} else if (newVal.length < orgLen) {
return intPart + dotPart + Array(orgLen - newVal.length + 1).join('0') + newVal;
} else {
return intPart + dotPart + newVal;
}
});
}
};
—— | chrome | firefox | ie |
---|---|---|---|
0.6 | 1 | 1 | 1 |
1.6 | 2 | 2 | 2 |
0.035 | 0.04 | 0.04 | 0.04 |
0.045 | 0.04 | 0.04 | 0.05 |
Number.prototype.toFixed = __toFixed;
String.prototype.toFixed = __toFixed;
console.log(0.6.toFixed(0));
console.log(1.6.toFixed(0));
console.log(0.035.toFixed(2));
console.log(0.045.toFixed(2));
console.log(new Number(200).toFixed(2));
console.log(new Number(200).toFixed(0));
console.log(new Number(1.23456789123456789).toFixed(5));
console.log("0.6".toFixed(0));
console.log("1.6".toFixed(0));
console.log("0.035".toFixed(2));
console.log("0.045".toFixed(2));
console.log("200".toFixed(2));
console.log("200".toFixed(0));
console.log("1.23456789123456789".toFixed(5));
function __toFixed(val) {
const value = +this.toString();
const decimal_number = this.toString().replace(/\d*\./, "").length;
const denominator = 10 ** (decimal_number - val > 0 ? decimal_number -
val : 0);
let current_value = Math.round(value * 10 ** decimal_number / denominator) * denominator / 10 ** decimal_number + "";
if (/\./.test(current_value)) {
const current_decimal_number = current_value.replace(/\d*\./, "").length;
if (current_decimal_number < val) {
current_value += "0".repeat(val - current_decimal_number);
}
} else if (val) {
current_value += "." + "0".repeat(val);
}
return current_value;
}
//zxx: 测试通过
第一题:'1'
第二题: '2'
第二题: '0.04'
第四题: '0.04' /chrome;'0.05'/ie
第五题:
Number.prototype.toFixed = function(n){
n = parseInt(n)
if (n < 0) return NaN
let num = this.valueOf()
let numStr = num +''
let pointPos = numStr.indexOf('.')
if (pointPos > -1){
//有小数部分
let decimal = numStr.slice(pointPos+1)
if (decimal.length < n) {
//小数位需要填零
let ret = numStr + (new Array(n - decimal.length).fill(0).join(''))
return ret
}else {
//正常四舍五入
//Math.round 对于负数也会有-4.5 =》 4 ; 4.5 =》 5
let m = Math.pow(10, n)
let flag = num > 0
let t = parseInt(Math.round(Math.abs(num) * m)) / m
t = flag ? t : -t
return t+''
}
}else {
//整数
return num+ ( n > 0 ? '.' + (new Array(n).fill(0).join('')) : '')
}
}
第六题:
String.prototype.toFixed = function(n){
let num = +this
if (isNaN(num)) return NaN
return num.toFixed(n)
}
//测试
console.log('0.6'.toFixed(0)) //1
console.log('1.6'.toFixed(0)) //2
console.log('0.035'.toFixed(2)) //0.04
console.log('0.045'.toFixed(2)) //0.05
console.log('-0.045'.toFixed(2)) //-0.05
console.log(('-100.525').toFixed(5)) //-100.125
console.log('100.8123'.toFixed(0)) //101
chrome 下
1. '1'
2. '2'
3. '0.04'
4. '0.04'
5.
// 数字+1
function numAdd(str) {
let flag = 1, newNum = ''
for (let i = str.length - 1; i >= 0; i--) {
if (str[i] === '.') {
newNum = '.' + newNum
continue
}
let res = (str[i] >> 0) + flag
flag = res >= 10 ? 1 : 0;
if (i === 0) {
newNum = (str[i] === '-' ? '-' : '') + res + newNum
} else {
newNum = (flag ? '0' : res) + newNum
}
}
return newNum
}
Number.prototype.toFixed = function (num) {
let strNum = (this + '')
const pointPos = strNum.indexOf('.')
const strArr = strNum.split('.')
// 如果保留有效数字的值比小数点后的数字大,补0
if (num !== 0) {
if (pointPos === -1) {
strNum += '.'
}
strNum = strNum.padEnd((strNum.length - pointPos - 1) + num, '0')
}
// 小数再判断四舍五入
if (pointPos !== -1) {
if (strArr[1].length > num) {
const newStr = strArr[0] + '.' + strArr[1].slice(0, num)
return (strArr[1][num] >= 5 ? numAdd(newStr) : newStr).replace(/\.$/, '')
} else {
return strNum
}
}
return strNum
}
console.log((0.6).toFixed(0),
(1.6).toFixed(0),
( 0.035).toFixed(2),
(0.045).toFixed(2))
6.
String.prototype.toFixed = function (num) {
if (parseFloat(num) + '' === 'NaN') {
return num
} else {
return Number.prototype.toFixed.call(this, num)
}
}
console.log('0.6'.toFixed(0),
'1.6'.toFixed(0),
'0.035'.toFixed(2),
'0.045'.toFixed(2))
1. 1
2. 2
3. 0.04
4. 0.04
产生这种bug的原因网上说是丢失精度,不过我觉得有可能是此方法是采用了其它的舍入方法,类似于四舍六入五留双的方法,当然也没有完全符合这些规则。 参考
Number.prototype.toFixed = function (num) {
return myFixed(this.valueOf(),num);
};
String.prototype.toFixed = function (num) {
if(isNaN(this.valueOf())){
return 'isNaN';
}
return myFixed(this.valueOf(),num);
};
function myFixed(number,num){
var numberString = number.toString();
var dotLength = 0;
var fact = number;
if(num<=0){
return number;
}
var dot = numberString.split(".")[1]?numberString.split(".")[1]:'';
var a = dot.slice(num,num+1);
if(a!=''){
if(parseInt(a)<5){
}else{
fact = Number(number) + Math.pow(10,-num);
}
}
var factString = fact.toString();
if(factString.split(".")[1]){
fact = factString.split(".")[0]+'.' + factString.split(".")[1].slice(0,num);
}else {
fact = factString.split(".")[0]+'.';
}
fact = fact.toString();
if(fact.split(".")[1]) {
dotLength = dot.length;
}
for (var i=0;i<num-dotLength;i++){
fact += '0';
}
return fact;
};
Chrome | Firefox | IE | |
---|---|---|---|
0.6.toFixed(0) | 1 | 1 | 1 |
1.6.toFixed(0) | 2 | 2 | 2 |
0.035.toFixed(2) | 0.04 | 0.04 | 0.04 |
0.045.toFixed(2) | 0.04 | 0.04 | 0.05 |
经测试,只有当保留小数位后面仅为5的时候会出现预期之外的结果,改为6就正常了,或者补一位小数
var NativetoFixed = Number.prototype.toFixed;//备份
//方式一:替换小数点保留精度后面一位5为6
var MytoFixed = function(digits){
var reg = new RegExp('(\\d*.\\d{' + digits + '})5(\\d*)', 'g')
var number = Number(this.toString().replace(reg, '$1' + 6 + '$2'));
return NativetoFixed.call(number,digits);
}
//方式二:给小数点保留精度后面补一位小数
var MytoFixed = function(digits){
var number = Number(this)+Math.pow(10,-digits-1);
return NativetoFixed.call(number,digits);
}
Number.prototype.toFixed = MytoFixed;
String.prototype.toFixed = MytoFixed;
//有错误:1.0141 .toFixed = 1.0141 + 0.001 = 1.151 -> toFixed(2) = 1.15
//zxx: 赞不一样的思路,富有创造力
-
1
-
2
-
0.04
-
0.04
-
Number.prototype.toFixed = function(v){ if(this === -Infinity) throw Error('-Infinity'); if(this === Infinity) throw Error('Infinity'); if(isNaN(this)) throw Error(this+'.toFixed is not a function') return parseInt(Math.round(this * Math.pow(10,v)))/Math.pow(10,v) }
-
String.prototype.toFixed = function(v){ var num = Number(this); if(!num) return 'Error Non-numeric string'; return parseInt(Math.round(num * Math.pow(10,v)))/Math.pow(10,v) }
// 1
document.write(0.6.toFixed(0));
document.write(" ");
// 2
document.write(1.6.toFixed(0));
document.write(" ");
// 3
document.write(0.035.toFixed(2));
document.write(" ");
// 4
document.write(0.045.toFixed(2));
document.write(" ");
// 5
Number.prototype.toFixed=function(v){
//增加 nan判断
if(!window.isNaN(this)){
let numberString = this.toString().split(".");
let isAddOne = ( numberString[1].slice(v,v+1) - 0 ) >= 5;
let result = "";
let beforePonit = numberString[0]+".";
if(v===0){
result = ((beforePonit + numberString[1].slice(0,v)) - 0 ) + (isAddOne ? 1 : 0) ;
}
else{
let addNumber="";
for(let i=0;i < v-1;i++){
addNumber = addNumber +"0";
}
result = ((beforePonit + numberString[1].slice(0,v)) - 0 ) +((beforePonit+ addNumber + (isAddOne ? 1:0) ) - 0 ) ;
}
return result;
}
}
// 6
String.prototype.toFixed = Number.prototype.toFixed;
/*
*
0.6.toFixed(0)
"1"
1.6.toFixed(0)
"2"
0.035.toFixed(0)
"0"
0.035.toFixed(2)
"0.04"
0.045.toFixed(2)
"0.04"
*
* */
Number.prototype.oldToFixed = Number.prototype.toFixed;
Number.prototype.toFixed=function(a){
let num = this - 0;
a = a-0;
if(!(a > 0 || a < 1)){
a = 0
}
let times = Math.pow(10,a);
let bigNum = num*times;
let str = bigNum+'';
if(str.indexOf('.')<0){
return num.oldToFixed(a)
}
else{
let numArr = str.split(".");
let integer = numArr[0];
let decimal = numArr[1];
if(decimal>4){
integer++
}
return integer/times
}
}
String.prototype.toFixed=function(a){
let num = this - 0;
if(!(num > 0 || num < 1)){
return num
}
return num.toFixed(a)
}
Chrome | Firefox | Safari | IE | |
---|---|---|---|---|
0.6.toFixed(0) | 1 | 1 | 1 | 1 |
1.6.toFixed(0) | 2 | 2 | 2 | 2 |
0.035.toFixed(2) | 0.04 | 0.04 | 0.04 | 0.04 |
0.045.toFixed(2) | 0.04 | 0.04 | 0.04 | 0.05 |
第五/六问 demo
- 一开始实现的方法,后面经过测试发现 toFixedFirstTime(1.015,2) 测试结果出错
function toFixedFirstTime(num, pre = 0) {
num = parseFloat(num)
// 非负数和取整
pre = pre < 0 ? 0 : ~~pre
// 计算四舍五入结果
const result = Math.round(num * Math.pow(10, pre)) / Math.pow(10, pre) + ''
// 将结果通过小数点分割成两个数字
const strArr = result.split('.')
// 如果存在小数点
if (strArr[1] !== undefined) {
const len = strArr[1].length
// 如果小数部分长度不及提供的数值大
if (len <= pre) {
return `${result}`.padEnd(pre + strArr[0].length + 1, 0)
} else {
return `${result}`
}
}
return (
// 加一是因为小数点的长度
`${result}` + (pre > 0 ? '.'.padEnd(pre + 1, 0) : '')
)
}
- 第二次重写 toFixed 函数, 测试 toFixedSecondTime(1.015,2) 成功
function toFixedSecondTime(num, pre = 0) {
pre = pre < 0 ? 0 : ~~pre
const strArr = `${num}`.split('.')
const index = `${num}`.indexOf('.')
if (strArr[1] !== undefined) {
const len = strArr[1].length
// 当指定数值比原数据的小数位长
if (len <= pre) {
return `${num}`.padEnd(pre + strArr[0].length + 1, 0)
} else {
// 最后一位数
const last = strArr[1].slice(pre, pre + 1)
// 小数点前数字长度
const firstLength = strArr[0].length
// 将源数据取出小数点变为一个整数
let str = strArr.join('').split('')
if (last >= 5) {
let addFlag = false
const res = str
// 取出小数点前以及小数点后 pre 位的数值
.slice(0, firstLength + pre)
// 将数组反转
.reverse()
// 判断是否需要进位
.reduce((res, acc, index) => {
if (index === 0 || addFlag) {
acc = parseInt(acc) + 1
addFlag = false
}
if (acc === 10) {
addFlag = true
acc = 0
}
res.push(acc)
return res
}, [])
// 将数组反转为原来的顺序
.reverse()
.join('')
// 判断 pre 是否为 0, 为 0 则不添加小数点
return (
`${res.slice(0, index)}` +
(pre > 0 ? `.${res.slice(index, index + pre)}` : '')
)
} else {
// 判断 pre 是否为 0, 为 0 则不添加小数点
return `${strArr[0]}` + (pre > 0 ? `.${strArr[1].substr(0, pre)}` : '')
}
}
}
return `${num}.`.padEnd(pre + `${num}`.length + 1, 0)
}
- 第一个测试函数失败原因为 1.015 * Math.pow(10, 2) 返回结果是 101.49999999999999, Math.round 后返回 101。返回的结果比正常的结果小了 1e-14, 经过测试将这个数值先跟原始数值相加再进行 toFixed ,可以得到期待的值
function toFixedThirdTime(num, pre) {
pre = pre < 0 ? 0 : ~~pre
num = parseFloat(num)
return (num + 1e-14).toFixed(pre)
}
Number.prototype.toMyFixed = String.prototype.toMyFixed = function(pre) {
pre = pre < 0 ? 0 : ~~pre
num = parseFloat(this)
return (num + 1e-14).toFixed(pre)
}
//zxx: 研究精神不错,恕我代码看得眼花,可读性这块并不算友好
弄了个turbo做测试
ie8 | ie9 | ie10 | edge | chrome | firefox | opera | |
---|---|---|---|---|---|---|---|
0.6.toFixed(0) | 0 | 1 | 1 | 1 | 1 | 1 | 1 |
1.6.toFixed(0) | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
0.035.toFixed(2) | 0.04 | 0.04 | 0.04 | 0.04 | 0.04 | 0.04 | 0.04 |
0.045.toFixed(2) | 0.05 | 0.05 | 0.05 | 0.05 | 0.04 | 0.04 | 0.04 |
参考简书上的一篇文章做了小调整
// 第五题
Number.prototype.toFixed = function(n) {
const number = this;
if (isNaN(number)) {
return number.toString();
}
if (typeof(n) == 'undefined' || n == 0) {
return (Math.round(number)).toString();
}
let result = number.toString();
const arr = result.split('.');
// 整数的情况
if (arr.length < 2) {
result += '.';
for (let i = 0; i < n; i += 1) {
result += '0';
}
return result;
}
const integer = arr[0];
const decimal = arr[1];
if (decimal.length == n) {
return result;
}
if (decimal.length < n) {
for (let i = 0; i < n - decimal.length; i += 1) {
result += '0';
}
return result;
}
result = integer + '.' + decimal.substr(0, n);
const last = decimal.substr(n, 1);
// 四舍五入,转换为整数再处理,避免浮点数精度的损失
if (parseInt(last, 10) >= 5&&result>0) {
const x = Math.pow(10, n);
result = (Math.round((parseFloat(result) * x)) + 1) / x;
result = result.toFixed(n);
}else if(parseInt(last, 10) >= 5&&result<0){
const x = Math.pow(10, n);
result = (Math.round((parseFloat(result) * x)) - 1) / x;
result = result.toFixed(n);
}
return result;
};
// 第六题
String.prototype.toFixed=Number.prototype.toFixed
1. "1"
2. "2"
3. "0.04"
4. "0.04"
5-6. 下面的方法完全以字符串的方式进行处理
function toFixedFn (digits) {
if (digits < 0) throw new Error("位数不得小于0");
let [intNum, floatNum] = this.toString().split(".");
// 若无小数部位,直接用原生toFixed
if (floatNum === undefined) return parseInt(intNum).toFixed(digits);
// 若 digits 为0,直接利用round取整
if (digits === 0) return Math.round(this)
// 若小数部位长度少于digits,进行补位
if (floatNum.length < digits) {
let diff = digits - floatNum.length
floatNum = parseInt(floatNum) * Math.pow(10, diff)
}
// 小数部位模拟取整
let reg = new RegExp(`(.{${digits}})`);
floatNum = Math.round(floatNum.toString().replace(reg, "$1.").slice(0, digits + 2))
floatNum = (floatNum / Math.pow(10, digits)).toString().slice(1)
// 处理完后,进行补位
if (floatNum.length - 1 < digits) {
floatNum = floatNum + '0'.repeat(digits - floatNum.length + 1)
}
return intNum + floatNum
};
Number.prototype.toFixedNum = toFixedFn
String.prototype.toFixedNum = toFixedFn
// 测试
console.log((0.6).toFixedNum(0));
console.log((1.6).toFixedNum(0));
console.log((0.035).toFixedNum(2));
console.log((0.045).toFixedNum(2));
console.log((0.2).toFixedNum(6));
console.log('0.6'.toFixedNum(0));
console.log('1.6'.toFixedNum(0));
console.log('0.035'.toFixedNum(2));
console.log('0.045'.toFixedNum(2));
console.log('0.2'.toFixedNum(6));
// 输出
1
2
"0.04"
"0.05"
"0.200000"
- 使用Node result: console.log(0.6.toFixed(0)) => 1 console.log(1.6.toFixed(0)) => 2 console.log(0.035.toFixed(2)) => 0.04 console.log(0.045.toFixed(2)) => 0.04
- chrome浏览器 result: console.log(0.6.toFixed(0)) => 1 console.log(1.6.toFixed(0)) => 2 console.log(0.035.toFixed(2)) => 0.04 console.log(0.045.toFixed(2)) => 0.04
第五题:
Number.prototype.toFixed = function(n) {
var power = Math.pow(10, n);
var value = this * power + 0.5;
value = parseInt(value, 10) / power;
return value;
};
第六题:
String.prototype.toFixed = function(n) {
var num = Number(this);
if(!num) return NaN;
var power = Math.pow(10, n);
var value = num * power + 0.5;
value = parseInt(value, 10) / power;
return value;
};
chrome
1. 1
2. 2
3. 0.04
4. 0.04
5.
let oldtoFixed = Number.prototype.toFixed
Number.prototype.toFixed = function(n) {
return oldtoFixed.call(Number.parseFloat(this+''+1), n)
}
// 有错误 new Number(10).toFixed(2) "101.00"
6. String.prototype.toFixed = Number.prototype.toFixed
本期要点:
- toFixed有两个问题,一是兼容性,二是四舍五入不符合正常的四舍五入认知。金钱计算的时候容易出问题,必须两位小数。
- 应该返回字符串;补全末尾的0。
- 机智是实现:方式一:替换小数点保留精度后面一位5为6,方式二:给小数点保留精度后面补一位小数。其中方式2是最简单的,XboxYan 和 frankyeyq 实现都有bug,下面是调整后的实现。
var oldtoFixed = Number.prototype.toFixed
Number.prototype.toFixed = function(digits){
var length = (parseFloat(this) + '').replace(/^\d+\.?/, '').length;
var len = length > digits ? length : digits;
var number = Number(this) + Math.pow(10, -len-1);
return oldtoFixed.call(number, digits);
}
var oldtoFixed = Number.prototype.toFixed Number.prototype.toFixed = function(digits){ var length = (parseFloat(this) + '').replace(/^\d+\.?/, '').length; var number = Number(this) + Math.pow(10, -length-1); return oldtoFixed.call(number, digits); }
length 判断存在问题, 如果是 10.toFixed(2) 会在小数点后一位添加 1 导致返回 10.10, 所以应该判断 length 和 digits 的大小
var oldtoFixed = Number.prototype.toFixed
Number.prototype.toMyFixed = function(digits){
var length = (parseFloat(this) + '').replace(/^\d+\.?/, '').length;
var len = length > digits ? length : digits
var number = Number(this) + Math.pow(10, -len-1);
return oldtoFixed.call(number, digits);
}
var oldtoFixed = Number.prototype.toFixed Number.prototype.toFixed = function(digits){ var length = (parseFloat(this) + '').replace(/^\d+\.?/, '').length; var number = Number(this) + Math.pow(10, -length-1); return oldtoFixed.call(number, digits); }
length 判断存在问题, 如果是 10.toFixed(2) 会在小数点后一位添加 1 导致返回 10.10, 所以应该判断 length 和 digits 的大小
var oldtoFixed = Number.prototype.toFixed Number.prototype.toMyFixed = function(digits){ var length = (parseFloat(this) + '').replace(/^\d+\.?/, '').length; var len = length > digits ? length : digits var number = Number(this) + Math.pow(10, -len-1); return oldtoFixed.call(number, digits); }
多谢反馈~