例如,假设我在8进制中有数字
12.24
(在10进制中为10.3125
),我想将这个数字舍入到1位小数,以便得到12.3
。12.24
(在10进制中为10.3125
),我想将这个数字舍入到1位小数,以便得到12.3
。There isn´t a function in js that can do this. So need to create one in order to do it. What it does is to check if the digit to fix (in your case the "4") is closer to the base (8) or closer to 0:
if (base - digit_tofix <= base / 2) {
然后,只需将差值加或减到10或0,因此如果数字是12.24
,则会返回:
return 12.24 + 0.06; // ---> equals to 12.3
12.23
,返回:return 12.23 - 0.03 // ---> equals to 12.2
因此可以制作出像这样的东西:
function round(n, base, precision) {
const digit_tofix = n.toString().split(".")[1].split("")[precision];
if (base - digit_tofix <= base / 2) {
return (n + (10 - digit_tofix) / Math.pow(10, precision + 1)).toFixed(precision);
}else {
return (n - digit_tofix / Math.pow(10, precision + 1)).toFixed(precision);
}
}
编辑: 但是,这种方法无法捕获进位溢出。因此,像这样的八进制数字:
55.74
将转变为:
55.74 + 0.06 = 55.8 // --> number 8 doesn´t exist in octal
do while()
循环进行 溢出检查。该语句的作用是将 digit_tofix
移动到前一个数字,并在每次加法运算时检查是否发生溢出:// Overflow check
do {
n += (10 - digit_tofix) / Math.pow(10, precision + 1);
precision--;
digit_tofix = precision > -1 ? n.toFixed(precision + 1).split(".")[1].split("")[precision] :
n.toFixed(0).split(".")[0].split("")[precision + n.toString().split(".")[0].split("").length];
} while(digit_tofix == base);
return n.toFixed(precision > -1 ? precision + 1 : 0);
round()
函数中的参数。以下是一些可行的示例:const oct = 12.24;
console.log( round(oct, 8, 1) );
function round(n, base, precision) {
let digit_tofix = n.toString().split(".")[1].split("")[precision];
if (base - digit_tofix <= base / 2) {
// Overflow check
do {
n += (10 - digit_tofix) / Math.pow(10, precision + 1);
precision--;
digit_tofix = precision > -1 ? n.toFixed(precision + 1).split(".")[1].split("")[precision] :
n.toFixed(0).split(".")[0].split("")[precision + n.toString().split(".")[0].split("").length];
} while(digit_tofix == base);
return n.toFixed(precision > -1 ? precision + 1 : 0);
}else {
return (n - digit_tofix / Math.pow(10, precision + 1)).toFixed(precision);
}
}
const bin = 10011.011;
console.log( round(bin, 2, 1) );
function round(n, base, precision) {
let digit_tofix = n.toString().split(".")[1].split("")[precision];
if (base - digit_tofix <= base / 2) {
// Overflow check
do {
n += (10 - digit_tofix) / Math.pow(10, precision + 1);
precision--;
digit_tofix = precision > -1 ? n.toFixed(precision + 1).split(".")[1].split("")[precision] :
n.toFixed(0).split(".")[0].split("")[precision + n.toString().split(".")[0].split("").length];
} while(digit_tofix == base);
return n.toFixed(precision > -1 ? precision + 1 : 0);
}else {
return (n - digit_tofix / Math.pow(10, precision + 1)).toFixed(precision);
}
}
function round(n, base, precision) {
// To get number value of letter: a = 10, b = 11, c = 12 ...
const getNumber = e => isNaN(e) ? e.charCodeAt(0) - 87 : parseInt(e);
// Just to check incompability and invalid parameters
const checkIncompatible = () => {
if (digits.reduce((a, d) => d == "." ? ++a : a, 0) > 1 ||
(digits.some(d => isNaN(d) && (getNumber(d) < 10 || getNumber(d) > 35) && d != "."))) return "Invalid Number";
if (digits.some(d => getNumber(d) >= base && d != ".")) return "Number doesn´t match base";
if (precision < 0) return "Invalid precision argument";
if (base < 2 || base > 36) return "Invalid base argument";
return false;
};
// Recursive function to carry overflow
const add = p => {
if (digits[p] == ".") add(p - 1);
else if (getNumber(digits[p]) + 1 == base) {
digits[p] = "0";
if (p > 0) add(p - 1);
else digits.unshift("1");
}else {
if (isNaN(digits[p])) digits[p] = String.fromCharCode(digits[p].charCodeAt(0) + 1);
else digits[p] = digits[p] < 9 ? parseInt(digits[p]) + 1 : "a" ;
}
};
n = n.toString().toLowerCase().split(",").join("."); // In case there is a comma
let digits = n.split("");
// Avoid problems with undefined array index and other issues
if (typeof digits[digits.indexOf(".") + 1 + precision] === "undefined" ||
digits.reduce((a, d) => d == "." ? ++a : a, 0) < 1) return n;
let state = checkIncompatible();
if (state) return state;
const digit_tofix = getNumber(digits[digits.indexOf(".") + 1 + precision]);
// Check if digit_tofix is closer to base or zero
if (base - digit_tofix <= base / 2) {
add(digits.indexOf(".") + precision);
}
// Splice the array to get the substring
digits.splice(digits.indexOf(".") + 1 + precision);
if (!precision) digits.splice(-1);
return digits.join("");
}
这个方案更加复杂,但是范围更广,因为你可以使用从2到36的任意数字,这意味着你可以使用十六进制。
与第一种方案类似,它检查需要修复的数字(在您的情况下为“4”)是否更接近基数(8)还是更接近0:
if (base - digit_tofix <= base / 2) {
"12.23"
"12.2"
但如果将数字转换为固定位数的数字时,该数字更接近进制,我们需要在前一个数字上加+1。因此,如果数字为:
"12.24"
它的子字符串是
"12.3" //--> 2 + 1 = 3
例如,如果 八进制 数字为:
"12.74"
它的子字符串应该是:
"13.0" // 7 + 1 = 8 (base is 8 so there is an overflow)
因此,存在一个名为 add()
的递归函数,以便在溢出的情况下进行处理。
round()
函数返回一个新数字的字符串。
console.log( round("c3.bf9", 16, 2) );
console.log( round("AA.D1", 16, 1) );
console.log( round("ff.fff", 16, 0) );
function round(n, base, precision) {
const getNumber = e => isNaN(e) ? e.charCodeAt(0) - 87 : parseInt(e);
const checkIncompatible = () => {
if (digits.reduce((a, d) => d == "." ? ++a : a, 0) > 1 ||
(digits.some(d => isNaN(d) && (getNumber(d) < 10 || getNumber(d) > 35) && d != "."))) return "Invalid Number";
if (digits.some(d => getNumber(d) >= base && d != ".")) return "Number doesn´t match base";
if (precision < 0) return "Invalid precision argument";
if (base < 2 || base > 36) return "Invalid base argument";
return false;
};
const add = p => {
if (digits[p] == ".") add(p - 1);
else if (getNumber(digits[p]) + 1 == base) {
digits[p] = "0";
if (p > 0) add(p - 1);
else digits.unshift("1");
}else {
if (isNaN(digits[p])) digits[p] = String.fromCharCode(digits[p].charCodeAt(0) + 1);
else digits[p] = digits[p] < 9 ? parseInt(digits[p]) + 1 : "a" ;
}
};
n = n.toString().toLowerCase().split(",").join(".");
let digits = n.split("");
if (typeof digits[digits.indexOf(".") + 1 + precision] === "undefined" ||
digits.reduce((a, d) => d == "." ? ++a : a, 0) < 1) return n;
let state = checkIncompatible();
if (state) return state;
const digit_tofix = getNumber(digits[digits.indexOf(".") + 1 + precision]);
if (base - digit_tofix <= base / 2) {
add(digits.indexOf(".") + precision);
}
digits.splice(digits.indexOf(".") + 1 + precision);
if (!precision) digits.splice(-1);
return digits.join("");
}
console.log( round(12.24, 8, 1) );
console.log( round(17.77, 8, 1) );
console.log( round(0.74, 8, 1) );
function round(n, base, precision) {
const getNumber = e => isNaN(e) ? e.charCodeAt(0) - 87 : parseInt(e);
const checkIncompatible = () => {
if (digits.reduce((a, d) => d == "." ? ++a : a, 0) > 1 ||
(digits.some(d => isNaN(d) && (getNumber(d) < 10 || getNumber(d) > 35) && d != "."))) return "Invalid Number";
if (digits.some(d => getNumber(d) >= base && d != ".")) return "Number doesn´t match base";
if (precision < 0) return "Invalid precision argument";
if (base < 2 || base > 36) return "Invalid base argument";
return false;
};
const add = p => {
if (digits[p] == ".") add(p - 1);
else if (getNumber(digits[p]) + 1 == base) {
digits[p] = "0";
if (p > 0) add(p - 1);
else digits.unshift("1");
}else {
if (isNaN(digits[p])) digits[p] = String.fromCharCode(digits[p].charCodeAt(0) + 1);
else digits[p] = digits[p] < 9 ? parseInt(digits[p]) + 1 : "a" ;
}
};
n = n.toString().toLowerCase().split(",").join(".");
let digits = n.split("");
if (typeof digits[digits.indexOf(".") + 1 + precision] === "undefined" ||
digits.reduce((a, d) => d == "." ? ++a : a, 0) < 1) return n;
let state = checkIncompatible();
if (state) return state;
const digit_tofix = getNumber(digits[digits.indexOf(".") + 1 + precision]);
if (base - digit_tofix <= base / 2) {
add(digits.indexOf(".") + precision);
}
digits.splice(digits.indexOf(".") + 1 + precision);
if (!precision) digits.splice(-1);
return digits.join("");
}
console.log( round(101.10, 2, 1) );
console.log( round("100,11", 2, 1) );
console.log( round(100.11, 2, 1) );
function round(n, base, precision) {
const getNumber = e => isNaN(e) ? e.charCodeAt(0) - 87 : parseInt(e);
const checkIncompatible = () => {
if (digits.reduce((a, d) => d == "." ? ++a : a, 0) > 1 ||
(digits.some(d => isNaN(d) && (getNumber(d) < 10 || getNumber(d) > 35) && d != "."))) return "Invalid Number";
if (digits.some(d => getNumber(d) >= base && d != ".")) return "Number doesn´t match base";
if (precision < 0) return "Invalid precision argument";
if (base < 2 || base > 36) return "Invalid base argument";
return false;
};
const add = p => {
if (digits[p] == ".") add(p - 1);
else if (getNumber(digits[p]) + 1 == base) {
digits[p] = "0";
if (p > 0) add(p - 1);
else digits.unshift("1");
}else {
if (isNaN(digits[p])) digits[p] = String.fromCharCode(digits[p].charCodeAt(0) + 1);
else digits[p] = digits[p] < 9 ? parseInt(digits[p]) + 1 : "a" ;
}
};
n = n.toString().toLowerCase().split(",").join(".");
let digits = n.split("");
if (typeof digits[digits.indexOf(".") + 1 + precision] === "undefined" ||
digits.reduce((a, d) => d == "." ? ++a : a, 0) < 1) return n;
let state = checkIncompatible();
if (state) return state;
const digit_tofix = getNumber(digits[digits.indexOf(".") + 1 + precision]);
if (base - digit_tofix <= base / 2) {
add(digits.indexOf(".") + precision);
}
digits.splice(digits.indexOf(".") + 1 + precision);
if (!precision) digits.splice(-1);
return digits.join("");
}
n
位数字,然后检查第n+1
位数字是否为 4、5、6 或 7,以有条件地增加前一位数字。(或者对于一般的基数B
,高于Math.ceil(B/2)
?我不知道如何处理奇数基数。)不要使用任何数字运算(除了在数字级别上进行比较和递增),因为你只是进行字符串到字符串的转换。 - apsillers((10.3125 * 32) & 7) > 4 ? ((10.3125 * 8) >> 0) / 8 + 16 :((10.3215 * 8) >> 0) / 8
- Jonas Wilms