所有分类
  • 所有分类
  • Html5资源
  • React资源
  • Vue资源
  • Php资源
  • ‌小程序资源
  • Python资源

Math.js高级数学运算与函数库使用详解

简介

Math.js 是一个强大的 JavaScript 和 Node.js 数学库。它拥有灵活的表达式解析器,支持符号计算,内置大量函数和常量,并提供集成解决方案,可处理各种数据类型,例如数字、大数、复数、分数、单位和矩阵。功能强大且易于使用。

安装

npm install mathjs

使用

import { create } from "mathjs";

const math = create(all);
console.log(math.evaluate("1 + 2 * 3")); // 7

常用函数

基础函数

math.abs(-1); // 1
math.add(2, 3); // 5
math.ceil(3.14); // 4
math.floor(3.14); // 3
math.log(10); // 2.302585092994046
math.max(1, 2, 3); // 3
math.min(1, 2, 3); // 1
math.pow(2, 3); // 8
math.round(3.14); // 3
math.sqrt(9); // 3
math.sub(5, 3); // 2
math.trunc(3.14); // 3

Evaluate 表达式

math.evaluate("2 + 3 * 4"); // 14

BigNumber 大数字

const math = create(all, {
  number: "BigNumber",
  precision: 64,
});

console.log(math.evaluate("0.1 + 0.2").toString()); // "0.3"

math.bignumber(0.1 + 0.2); // 0.30000000000000004
math.bignumber(0.1).plus(0.2); // 0.3

不启用 bigNumber 配置,默认使用 number 类型, math.evaluate(“0.1 + 0.2”)结果为 0.30000000000000004

math.js 中大多数函数都支持 bigNumber 类型,但部分函数不支持,如 math.random()。

一些容易误入的误差,觉得使用了 bignumber 就可以避免浮点数精度问题,方法不对,也是不能解决问题的。

math.add(0.1, 0.2); // 0.30000000000000004

理想上,结果应该是 0.3,但实际结果却是 0.30000000000000004。这是因为 JavaScript 中的浮点数表示方式导致的精度问题。
那应该如何使用 bigNumber 来避免这个问题呢?

math.add(math.bignumber(0.1), math.bignumber(0.2)); // 0.3

通过将数字转换为 bigNumber 类型,可以避免浮点数精度问题,得到正确的结果。

Bigint 大整数

const math = create(all, {
  number: "bigint",
});

console.log(math.evaluate("70000000000000000123")); // 70000000000000000123n

注意:bigint 只能用于整数运算,不能用于浮点数运算。因此不能适用于三角函数。因为它会转换为 number,再执函数。

console.log(math.sin(2n)); // 0.9092974268256817

Fraction 分数

const math = create(all, {
  number: "Fraction",
});
console.log(math.fraction("2/5")); // Fraction { s: 1n, d: 5n, n: 2n }

Complex 复数

const math = create(all, {
  number: "Complex",
});
console.log(math.complex("2+3i")); // Complex { re: 2, im: 3 }

Unit 单位

const math = create(all, {
  number: "Unit",
});
console.log(math.unit("5cm")); // Unit { prefix: 'c', unit: 'm', value: 0.05 }

Matrix 矩阵

const math = create(all, {
  matrix: "Matrix",
});

console.log(
  math.matrix([
    [1, 2],
    [3, 4],
  ])
); // Matrix [[1, 2], [3, 4]]

使用场景

计算器

import { create, all } from "mathjs";
import { useState } from "react";

const math = create(all, {
  number: "BigNumber",
});

export default function MathDemo() {
  const [display, setDisplay] = useState("0");
  const [equation, setEquation] = useState("");
  const [isNewNumber, setIsNewNumber] = useState(true);
  const [isScientificMode, setIsScientificMode] = useState(false);

  const handleNumber = (num) => {
    if (isNewNumber) {
      setDisplay(num);
      setIsNewNumber(false);
    } else {
      setDisplay(display + num);
    }
  };

  const handleOperator = (operator) => {
    setEquation(display + " " + operator + " ");
    setIsNewNumber(true);
  };

  const handleScientificFunction = (func) => {
    try {
      let result;
      switch (func) {
        case "sin":
          result = math.sin(math.unit(display, "deg"));
          break;
        case "cos":
          result = math.cos(math.unit(display, "deg"));
          break;
        case "tan":
          result = math.tan(math.unit(display, "deg"));
          break;
        case "log":
          result = math.log10(parseFloat(display));
          break;
        case "ln":
          result = math.log(parseFloat(display));
          break;
        case "sqrt":
          result = math.sqrt(parseFloat(display));
          break;
        case "square":
          result = math.pow(parseFloat(display), 2);
          break;
        case "pi":
          result = math.pi;
          break;
        case "e":
          result = math.e;
          break;
        default:
          return;
      }
      setDisplay(result.toString());
      setIsNewNumber(true);
    } catch (error) {
      setDisplay("Error");
      setIsNewNumber(true);
    }
  };

  const handleEqual = () => {
    try {
      const result = math.evaluate(equation + display);
      setDisplay(result.toString());
      setEquation("");
      setIsNewNumber(true);
    } catch (error) {
      setDisplay("Error");
      setEquation("");
      setIsNewNumber(true);
    }
  };

  const handleClear = () => {
    setDisplay("0");
    setEquation("");
    setIsNewNumber(true);
  };

  const handleBackspace = () => {
    if (display.length > 1) {
      setDisplay(display.slice(0, -1));
    } else {
      setDisplay("0");
      setIsNewNumber(true);
    }
  };

  const basicButtons = [
    { label: "7", onClick: () => handleNumber("7") },
    { label: "8", onClick: () => handleNumber("8") },
    { label: "9", onClick: () => handleNumber("9") },
    { label: "÷", onClick: () => handleOperator("/") },
    { label: "4", onClick: () => handleNumber("4") },
    { label: "5", onClick: () => handleNumber("5") },
    { label: "6", onClick: () => handleNumber("6") },
    { label: "×", onClick: () => handleOperator("*") },
    { label: "1", onClick: () => handleNumber("1") },
    { label: "2", onClick: () => handleNumber("2") },
    { label: "3", onClick: () => handleNumber("3") },
    { label: "-", onClick: () => handleOperator("-") },
    { label: "0", onClick: () => handleNumber("0") },
    { label: ".", onClick: () => handleNumber(".") },
    { label: "=", onClick: handleEqual },
    { label: "+", onClick: () => handleOperator("+") },
  ];

  const scientificButtons = [
    { label: "sin", onClick: () => handleScientificFunction("sin") },
    { label: "cos", onClick: () => handleScientificFunction("cos") },
    { label: "tan", onClick: () => handleScientificFunction("tan") },
    { label: "log", onClick: () => handleScientificFunction("log") },
    { label: "ln", onClick: () => handleScientificFunction("ln") },
    { label: "√", onClick: () => handleScientificFunction("sqrt") },
    { label: "x²", onClick: () => handleScientificFunction("square") },
    { label: "π", onClick: () => handleScientificFunction("pi") },
    { label: "e", onClick: () => handleScientificFunction("e") },
    { label: "(", onClick: () => handleNumber("(") },
    { label: ")", onClick: () => handleNumber(")") },
    { label: "^", onClick: () => handleOperator("^") },
  ];

  return (
    <div className="flex flex-col items-center justify-center min-h-screen bg-black">
      <div className="w-96 bg-zinc-900 rounded-xl shadow-2xl p-6 border border-zinc-800">
        <div className="mb-6">
          <div className="text-right text-zinc-500 text-sm h-6 font-mono">
            {equation}
          </div>
          <div className="text-right text-4xl font-bold h-14 text-white font-mono">
            {display}
          </div>
        </div>
        <div className="flex justify-between mb-4">
          <button
            onClick={handleClear}
            className="bg-zinc-800 text-white px-4 py-2 rounded-lg hover:bg-zinc-700 transition-colors font-mono"
          >
            Clear
          </button>
          <button
            onClick={handleBackspace}
            className="bg-zinc-800 text-white px-4 py-2 rounded-lg hover:bg-zinc-700 transition-colors font-mono"
          >
            ←
          </button>
          <button
            onClick={() => setIsScientificMode(!isScientificMode)}
            className="bg-zinc-800 text-white px-4 py-2 rounded-lg hover:bg-zinc-700 transition-colors font-mono"
          >
            {isScientificMode ? "Basic" : "Scientific"}
          </button>
        </div>
        {isScientificMode && (
          <div className="grid grid-cols-4 gap-3 mb-4">
            {scientificButtons.map((button, index) => (
              <button
                key={index}
                onClick={button.onClick}
                className="bg-zinc-800 hover:bg-zinc-700 p-3 rounded-lg text-sm font-mono text-white transition-all duration-200 hover:shadow-lg hover:shadow-zinc-700/20"
              >
                {button.label}
              </button>
            ))}
          </div>
        )}
        <div className="grid grid-cols-4 gap-3">
          {basicButtons.map((button, index) => (
            <button
              key={index}
              onClick={button.onClick}
              className={`p-4 rounded-lg text-lg font-mono transition-all duration-200 ${
                button.label === "="
                  ? "bg-white text-black hover:bg-zinc-200 hover:shadow-lg hover:shadow-white/20"
                  : "bg-zinc-800 text-white hover:bg-zinc-700 hover:shadow-lg hover:shadow-zinc-700/20"
              }`}
            >
              {button.label}
            </button>
          ))}
        </div>
      </div>
    </div>
  );
}

购物车计算

import React, { useState, useEffect } from "react";
import { create, all } from "mathjs";

const math = create(all, {
  number: "BigNumber",
  precision: 20,
});

const ShoppingCart = () => {
  const [items, setItems] = useState([
    { id: 1, name: "Product 1", price: "1299.99", quantity: 1 },
    { id: 2, name: "Product 2", price: "49.99", quantity: 1 },
    { id: 3, name: "Product 3", price: "599.99", quantity: 1 },
  ]);

  const [cartTotal, setCartTotal] = useState("0");
  const [discount, setDiscount] = useState("0");
  const [tax, setTax] = useState("0");
  const [finalTotal, setFinalTotal] = useState("0");

  const calculateTotals = () => {
    try {
      // Calculate subtotal
      const subtotal = items.reduce((acc, item) => {
        return math.add(
          acc,
          math.multiply(
            math.bignumber(item.price),
            math.bignumber(item.quantity)
          )
        );
      }, math.bignumber(0));

      // Calculate discount (10% if total > 1000)
      const discountAmount =
        math.compare(subtotal, 1000) === 1
          ? math.multiply(subtotal, 0.1)
          : math.bignumber(0);

      // Calculate tax (8%)
      const taxAmount = math.multiply(
        math.subtract(subtotal, discountAmount),
        0.08
      );

      // Calculate final total
      const total = math.add(
        math.subtract(subtotal, discountAmount),
        taxAmount
      );

      setCartTotal(math.format(subtotal, { precision: 2 }));
      setDiscount(math.format(discountAmount, { precision: 2 }));
      setTax(math.format(taxAmount, { precision: 2 }));
      setFinalTotal(math.format(total, { precision: 2 }));
    } catch (error) {
      console.error("Calculation error:", error);
    }
  };

  useEffect(() => {
    calculateTotals();
  }, [items]);

  const handleQuantityChange = (id, newQuantity) => {
    if (newQuantity < 1) return;
    setItems(
      items.map((item) =>
        item.id === id ? { ...item, quantity: newQuantity } : item
      )
    );
  };

  const handleRemoveItem = (id) => {
    setItems(items.filter((item) => item.id !== id));
  };

  return (
    <div className="min-h-screen bg-zinc-900 text-white p-8">
      <div className="max-w-4xl mx-auto">
        <h1 className="text-4xl font-bold mb-8 text-center">Shopping Cart</h1>
        <div className="bg-zinc-800 rounded-xl p-6 shadow-2xl">
          <div className="space-y-4">
            {items.map((item) => (
              <div
                key={item.id}
                className="flex items-center justify-between bg-zinc-700 p-4 rounded-lg"
              >
                <div className="flex-1">
                  <h3 className="text-xl font-semibold">{item.name}</h3>
                  <p className="text-zinc-300">${item.price}</p>
                </div>
                <div className="flex items-center space-x-4">
                  <div className="flex items-center space-x-2">
                    <button
                      onClick={() =>
                        handleQuantityChange(item.id, item.quantity - 1)
                      }
                      className="bg-zinc-600 hover:bg-zinc-500 w-8 h-8 rounded-lg flex items-center justify-center transition-colors"
                    >
                      -
                    </button>
                    <span className="w-8 text-center">{item.quantity}</span>
                    <button
                      onClick={() =>
                        handleQuantityChange(item.id, item.quantity + 1)
                      }
                      className="bg-zinc-600 hover:bg-zinc-500 w-8 h-8 rounded-lg flex items-center justify-center transition-colors"
                    >
                      +
                    </button>
                  </div>
                  <button
                    onClick={() => handleRemoveItem(item.id)}
                    className="bg-red-500 hover:bg-red-600 px-4 py-2 rounded-lg transition-colors"
                  >
                    Remove
                  </button>
                </div>
              </div>
            ))}
          </div>
          <div className="mt-8 space-y-2 border-t border-zinc-700 pt-4">
            <div className="flex justify-between text-lg">
              <span>Subtotal:</span>
              <span>${cartTotal}</span>
            </div>
            <div className="flex justify-between text-lg text-green-400">
              <span>Discount (10% if total {">"} $1000):</span>
              <span>-${discount}</span>
            </div>
            <div className="flex justify-between text-lg">
              <span>Tax (8%):</span>
              <span>${tax}</span>
            </div>
            <div className="flex justify-between text-2xl font-bold mt-4 pt-4 border-t border-zinc-700">
              <span>Total:</span>
              <span>${finalTotal}</span>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

export default ShoppingCart;
原文链接:https://code.ifrontend.net/archives/355,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?