237 lines
5.6 KiB
JavaScript

/**
* 基本算术运算
* @param {string} expression 算术表达式
* @returns {number} 计算结果
*/
function evaluate(expression) {
// 移除所有空白字符
expression = expression.toString().replace(/\s+/g, "");
// 检查表达式是否为空
if (!expression) {
throw new Error("表达式不能为空");
}
// 检查表达式是否包含非法字符
if (!/^[0-9+\-*/().]+$/.test(expression)) {
throw new Error("表达式包含非法字符");
}
// 检查括号是否匹配
let bracketCount = 0;
for (const char of expression) {
if (char === "(") bracketCount++;
if (char === ")") bracketCount--;
if (bracketCount < 0) {
throw new Error("括号不匹配");
}
}
if (bracketCount !== 0) {
throw new Error("括号不匹配");
}
try {
// 将表达式中的数字转换为整数计算,使用固定精度
const scale = Math.pow(10, 15); // 使用固定的15位精度
const processedExpression = expression.replace(/\d*\.?\d+/g, (match) => {
const num = parseFloat(match);
return Math.round(num * scale);
});
// 使用 Function 构造函数创建一个安全的计算环境
const result = new Function(`return ${processedExpression}`)();
// 检查结果是否为有限数
if (!Number.isFinite(result)) {
throw new Error("计算结果无效");
}
// 还原小数位数
return result / scale;
} catch (error) {
throw new Error("表达式计算错误: " + error.message);
}
}
/**
* 处理两个数的加法,避免浮点数精度问题
* @param {number} a 第一个数
* @param {number} b 第二个数
* @returns {number} 计算结果
*/
function add(a, b) {
const precision = Math.max(
(a.toString().split(".")[1] || "").length,
(b.toString().split(".")[1] || "").length
);
const scale = Math.pow(10, precision);
return (Math.round(a * scale) + Math.round(b * scale)) / scale;
}
/**
* 处理两个数的减法,避免浮点数精度问题
* @param {number} a 第一个数
* @param {number} b 第二个数
* @returns {number} 计算结果
*/
function subtract(a, b) {
const precision = Math.max(
(a.toString().split(".")[1] || "").length,
(b.toString().split(".")[1] || "").length
);
const scale = Math.pow(10, precision);
return (Math.round(a * scale) - Math.round(b * scale)) / scale;
}
/**
* 处理两个数的乘法,避免浮点数精度问题
* @param {number} a 第一个数
* @param {number} b 第二个数
* @returns {number} 计算结果
*/
function multiply(a, b) {
const precision =
(a.toString().split(".")[1] || "").length +
(b.toString().split(".")[1] || "").length;
const scale = Math.pow(10, precision);
return (Math.round(a * scale) * Math.round(b * scale)) / (scale * scale);
}
/**
* 处理两个数的除法,避免浮点数精度问题
* @param {number} a 第一个数
* @param {number} b 第二个数
* @param {number} [precision=10] 精度
* @returns {number} 计算结果
*/
function divide(a, b, precision = 10) {
if (b === 0) {
throw new Error("除数不能为零");
}
const scale = Math.pow(10, precision);
return Math.round(a * scale) / Math.round(b * scale);
}
/**
* 计算阶乘
* @param {number} n 非负整数
* @returns {number} 阶乘结果
*/
function factorial(n) {
if (!Number.isInteger(n)) {
throw new Error("阶乘只能计算整数");
}
if (n < 0) {
throw new Error("阶乘不能计算负数");
}
if (n > 170) {
throw new Error("数字过大,可能导致溢出");
}
let result = 1;
for (let i = 2; i <= n; i++) {
result *= i;
}
return result;
}
/**
* 计算绝对值
* @param {number} x 数字
* @returns {number} 绝对值
*/
function abs(x) {
// 将数字转换为整数计算,使用固定精度
const scale = Math.pow(10, 15); // 使用固定的15位精度
const num = parseFloat(x.toString());
const result = Math.abs(Math.round(num * scale));
return result / scale;
}
/**
* 向上取整
* @param {number} x 数字
* @returns {number} 向上取整结果
*/
function ceil(x) {
return Math.ceil(x);
}
/**
* 向下取整
* @param {number} x 数字
* @returns {number} 向下取整结果
*/
function floor(x) {
return Math.floor(x);
}
/**
* 四舍五入
* @param {number} x 数字
* @param {number} [decimals=0] 保留小数位数
* @returns {number} 四舍五入结果
*/
function round(x, decimals = 0) {
if (!Number.isInteger(decimals) || decimals < 0) {
throw new Error("小数位数必须是非负整数");
}
const factor = Math.pow(10, decimals);
return Math.round(x * factor) / factor;
}
/**
* 计算平方根
* @param {number} x 非负数
* @returns {number} 平方根
*/
function sqrt(x) {
if (x < 0) {
throw new Error("不能计算负数的平方根");
}
return Math.sqrt(x);
}
/**
* 计算幂
* @param {number} base 底数
* @param {number} exponent 指数
* @returns {number} 幂运算结果
*/
function pow(base, exponent) {
const result = Math.pow(base, exponent);
if (!Number.isFinite(result)) {
throw new Error("计算结果超出范围");
}
return result;
}
/**
* 计算对数
* @param {number} x 正数
* @param {number} [base=Math.E] 底数
* @returns {number} 对数值
*/
function log(x, base = Math.E) {
if (x <= 0) {
throw new Error("对数只能计算正数");
}
if (base <= 0 || base === 1) {
throw new Error("对数的底数必须是大于0且不等于1的数");
}
return base === Math.E ? Math.log(x) : Math.log(x) / Math.log(base);
}
module.exports = {
evaluate,
factorial,
abs,
ceil,
floor,
round,
sqrt,
pow,
log,
};