Files
rime_wanxiang/lua/super_calculator.lua
2026-01-21 17:43:36 +08:00

3492 lines
125 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- author: https://github.com/ChaosAlphard
-- 说明 https://github.com/gaboolic/rime-shuangpin-fuzhuma/pull/41
-- 原有功能:
-- 单个随机数生成、三角函数、幂函数、指数函数、对数函数求值
-- 计算n次方根、平均值、方差、阶乘、角度与弧度的相互转化
-- 新增功能:
-- 求解一元一次方程、二元一次方程组、一元二次方程、一元三次方程、一元四次方程;
-- 求解一次、二次函数解析式、圆的方程;
-- 取整函数(包括向上取整和向下取整)、求余函数;
-- 已知数列中任意两项,求通项公式(等差或等比)求数列的前n项和(等差或等比)
-- 已知三角形三边长求面积已知正多边形边数n、边长a求面积
-- 判断两直线位置关系,给出距离或交点坐标;点到点、点到直线距离求解;
-- 求解两点间线段的垂直平分线方程;求解点绕点旋转后的坐标;
-- 组合数、排列数、最大公因数、最小公倍数求解;
-- 点关于直线的对称点坐标、直线关于直线(或点)的对称直线方程求解;
-- 连续自然数的幂方求和包括平方和、立方和、4次方之和前n个奇数或偶数的平方和、立方和、4次方之和
-- 求解勾股数、批量随机数、质因数分解、找质数;
-- 24点计算器(姑且算一个小游戏,雾)
-- 常见单位间的换算;数字的进制转换;
-- 功能引导键一览:
-- cb = "连续自然数立方和(从1开始)"
-- fp = "连续自然数4次方之和(从1开始)"
-- sq = "连续自然数平方和(从1开始)"
-- tx = "已知数列的任意两项aᵢ、aₖ及对应的项数i、k求其通项公式"
-- avg = "平均值"
-- cos = "余弦"
-- deg = "弧度转换为角度"
-- dds = "顶点式求解二次函数解析式"
-- dxf = "点斜法求解一次函数解析式"
-- ecb = "前n个偶数的立方和"
-- efp = "前n个偶数的4次方之和"
-- esq = "前n个偶数的平方和"
-- exp = "返回 e^x"
-- gbs = "计算多个数的最小公倍数"
-- ggs = "求解勾股数"
-- gys = "计算多个数的最大公因数"
-- hls = "计算行列式"
-- ldf = "两点法求解一次函数解析式"
-- ld1 = "已知两点坐标,求两点间的距离"
-- ld2 = "已知两点坐标,求两点间线段的垂直平分线方程"
-- ld3 = "已知两点P(x₁, y₁)和Q(x₂, y₂)求点P绕点Q旋转角度a(角度制)后的P'坐标"
-- log = "x作为底数的对数"
-- mod = "求余函数"
-- msq = "计算正数的算术平方根"
-- nrt = "计算 x 开 N 次方"
-- ocb = "前n个奇数的立方和"
-- ofp = "前n个奇数的4次方之和"
-- osq = "前n个奇数的平方和"
-- pls = "计算排列数"
-- rad = "角度转换为弧度"
-- sin = "正弦"
-- sjs = "随机数"
-- tan = "正切"
-- tfp = "24点计算器"
-- var = "方差"
-- ybs = "一般式求解二次函数解析式"
-- zhs = "计算组合数"
-- zys = "质因数分解"
-- zzs = "找质数"
-- acos = "反余弦"
-- asin = "反正弦"
-- atan = "反正切"
-- cesd = "已知圆上不同三点的坐标,求圆方程"
-- cexl = "已知圆心和圆上不同两点的坐标求圆方程"
-- cexr = "已知圆心坐标和半径求圆的方程"
-- cosh = "双曲余弦"
-- dbsl = "已知等比数列的首项a₁公比q求指定的前n项和"
-- dcsl = "已知等差数列的首项a₁公差d求指定的前n项和"
-- dwhs = "单位换算,支持面积、质量、长度、体积,(数字, '原单位', '目标单位')"
-- eyyc = "求解二元一次方程组ax+by=ecx+dy=f"
-- fact = "阶乘"
-- lzx1 = "已知两直线方程A₁x+B₁y+C₁=0和A₂x+B₂y+C₂=0判断它们的位置关系"
-- lzx2 = "已知直线l₁:A₁x+B₁y+C₁=0和l₂:A₂x+B₂y+C₂=0求两条直线以彼此为轴的对称直线方程"
-- loge = "e作为底数的对数"
-- logt = "10作为底数的对数"
-- jzzh = "数字进制转换支持2~36进制(数字, 原进制, 目标进制)"
-- psjs = "批量随机数"
-- sinh = "双曲正弦"
-- sjxx = "已知三角形三个顶点坐标,求其“心”的坐标"
-- sjx1 = "已知三角形的三边长a、b、c求三角形面积"
-- sjx2 = "已知三角形的三个顶点坐标(x₁,y₁)(x₂,y₂)(x₃,y₃),求三角形面积"
-- sqrt = "计算复数的平方根"
-- tanh = "双曲正切"
-- tcr1 = "已知两圆标准方程(x-x₁)²+(y-y₁)²=r₁²和(x-x₂)²+(y-y₂)²=r₂²判断它们的位置关系"
-- tcr2 = "已知两圆一般方程x²+y²+D₁x+E₁y+F₁=0和x²+y²+D₂x+E₂y+F₂=0判断它们的位置关系"
-- yyec = "求解一元二次方程"
-- yyyc = "求解一元一次方程"
-- xsqz = "向上取整"
-- xxqz = "向下取整"
-- zdbx = "已知边数n与边长a计算正多边形面积"
-- atan2 = "返回以弧度为单位的点(x,y)相对于x轴的逆时针角度"
-- dyzx1 = "已知一点坐标(x₁,y₁)和直线方程Ax+By+C=0求点到直线的距离及对称点坐标"
-- dyzx2 = "已知一点P(x₁,y₁)和直线l:Ax+By+C=0求直线l关于点P的对称直线l'的方程"
-- ldexp = "返回 x*2^y"
-- sjxy1 = "已知三角形三边长,求内切圆半径和外接圆半径"
-- sjxy2 = "已知三角形三个顶点坐标,求内切圆半径和外接圆半径"
-- yysc1 = "求解一元三次方程"
-- yysc2 = "求解一元四次方程"
local T = {}
function T.init(env)
local config = env.engine.schema.config
env.name_space = env.name_space:gsub('^*', '')
local _calc_pat = config:get_string("recognizer/patterns/calculator") or nil
T.prefix = _calc_pat and _calc_pat:match("%^.?([a-zA-Z/=]+).*") or "V"
T.tips = config:get_string("calculator/tips") or "计算器"
end
local function startsWith(str, start)
return string.sub(str, 1, string.len(start)) == start
end
-- 函数表
local calc_methods = {
-- e, exp(1) = e^1 = e
e = math.exp(1),
-- π
pi = math.pi,
b = 10 ^ 2,
q = 10 ^ 3,
k = 10 ^ 3,
w = 10 ^ 4,
tw = 10 ^ 5,
m = 10 ^ 6,
tm = 10 ^ 7,
y = 10 ^ 8,
g = 10 ^ 9
}
local methods_desc = {
["e"] = "自然常数, 欧拉数",
["pi"] = "圆周率 π",
["b"] = "",
["q"] = "",
["k"] = "",
["w"] = "",
["tw"] = "十万",
["m"] = "百万",
["tm"] = "千万",
["y"] = "亿",
["g"] = "十亿"
}
-- 实现计算输入
local function replaceToFactorial(str)
return str:gsub("([0-9]+)!", "fact(%1)")
end
-- 保留返回值的非零有效数字(返回结果为数字)
local function fn(n)
-- 将数字转换为字符串以便处理
local s = tostring(n)
-- 查找小数点的位置
local i = string.find(s, "%.")
if i == nil then
-- 如果没有小数点,直接返回原数字
return n
end
-- 去除小数点后的尾随零
local j = string.len(s)
while j > i and string.sub(s, j, j) == "0" do
j = j - 1
end
-- 如果小数点后没有数字了,移除小数点
if j == i then
-- 返回整数部分
return tonumber(string.sub(s, 1, i - 1))
else
-- 否则,返回处理后的数字
return tonumber(string.sub(s, 1, j))
end
end
-- 保留返回值的非零有效数字(返回结果为字符串)
local function fs(n)
-- 将数字转换为字符串以便处理
local s = tostring(n)
-- 查找小数点的位置
local i = string.find(s, "%.")
if i == nil then
-- 如果没有小数点,直接返回原数字
return n
end
-- 去除小数点后的尾随零
local j = string.len(s)
while j > i and string.sub(s, j, j) == "0" do
j = j - 1
end
-- 如果小数点后没有数字了,移除小数点
if j == i then
-- 返回整数部分
return string.sub(s, 1, i - 1)
else
-- 否则,返回处理后的数字
return string.sub(s, 1, j)
end
end
-- 向上取整函数
local function ceil(x)
return math.ceil(x)
end
calc_methods["xsqz"] = ceil
methods_desc["xsqz"] = "向上取整"
-- 向下取整函数
local function floor(x)
return math.floor(x)
end
calc_methods["xxqz"] = floor
methods_desc["xxqz"] = "向下取整"
-- 四舍五入保留小数点后n位
local function round(m, n)
local factor = 10 ^ n
return floor(m * factor + 0.5) / factor
end
local function format_number_for_display(n)
if type(n) ~= "number" then
return tostring(n)
end
-- 分离整数部分和小数部分
local integer_part = math.floor(math.abs(n))
local integer_digits = #tostring(integer_part)
-- 只检查整数部分的位数
if integer_digits > 19 then
return "数字超限!"
end
-- 检查是否为整数
if n == math.floor(n) then
return tostring(math.floor(n))
end
-- 四舍五入到12位小数
local rounded = round(n, 12)
-- 使用fs函数转换为字符串并去除尾随0
return fs(rounded)
end
-- 计算两个数的最大公因数GCD
local function gcd(a, b)
while b ~= 0 do
local temp = b
b = a % b
a = temp
end
return a
end
-- 计算多个数的最大公因数
local function gcd_multiple(...)
local nums, result
nums = { ... }
result = nums[1]
for i = 2, #nums do
result = gcd(result, nums[i])
end
return fn(result)
end
calc_methods["gys"] = gcd_multiple
methods_desc["gys"] = "计算多个数的最大公因数"
-- 计算两个数的最小公倍数LCM
local function lcm(a, b)
return a * b / gcd(a, b)
end
-- 计算多个数的最小公倍数
local function lcm_multiple(...)
local nums, result
nums = { ... }
result = nums[1]
for i = 2, #nums do
result = lcm(result, nums[i])
end
return fn(result)
end
calc_methods["gbs"] = lcm_multiple
methods_desc["gbs"] = "计算多个数的最小公倍数"
-- random(m ,n) 返回m-n之间的随机数n为空则返回1-m之间都为空则返回0-1之间的小数
local function random(...)
return math.random(...)
end
-- 注册到函数表中
calc_methods["sjs"] = random
methods_desc["sjs"] = "随机数"
-- 计算开 N 次方
local function nth_root(x, n)
if n % 2 == 0 and x < 0 then
return nil -- 偶次方时负数没有实数解
elseif x < 0 then
return -((-x) ^ (1 / n))
else
return x ^ (1 / n)
end
end
calc_methods["nrt"] = nth_root
methods_desc["nrt"] = "计算 x 开 N 次方"
-- 正弦
local function sin(x)
return math.sin(x)
end
calc_methods["sin"] = sin
methods_desc["sin"] = "正弦"
-- 双曲正弦
local function sinh(x)
return (math.exp(x) - math.exp(-x)) / 2
end
calc_methods["sinh"] = sinh
methods_desc["sinh"] = "双曲正弦"
-- 反正弦
local function asin(x)
return math.asin(x)
end
calc_methods["asin"] = asin
methods_desc["asin"] = "反正弦"
-- 余弦
local function cos(x)
return math.cos(x)
end
calc_methods["cos"] = cos
methods_desc["cos"] = "余弦"
-- 双曲余弦
local function cosh(x)
return (math.exp(x) + math.exp(-x)) / 2
end
calc_methods["cosh"] = cosh
methods_desc["cosh"] = "双曲余弦"
-- 反余弦
local function acos(x)
return math.acos(x)
end
calc_methods["acos"] = acos
methods_desc["acos"] = "反余弦"
-- 正切
local function tan(x)
return math.tan(x)
end
calc_methods["tan"] = tan
methods_desc["tan"] = "正切"
-- 双曲正切
local function tanh(x)
local e = math.exp(2 * x)
return (e - 1) / (e + 1)
end
calc_methods["tanh"] = tanh
methods_desc["tanh"] = "双曲正切"
-- 反正切
local function atan(x)
return math.atan(x)
end
calc_methods["atan"] = atan
methods_desc["atan"] = "反正切"
-- 返回以弧度为单位的点(x,y)相对于x轴的逆时针角度。y是点的纵坐标x是点的横坐标
-- 返回范围从−π到π (以弧度为单位),其中负角度表示向下旋转,正角度表示向上旋转
-- 它与传统的 math.atan(y/x) 函数相比具有更好的数学定义因为它能够正确处理边界情况例如x=0
local function atan2(y, x)
if x == 0 and y == 0 then
return 0 / 0 -- 返回NaN
elseif x == 0 and y ~= 0 then
if y > 0 then
return math.pi / 2
else
return -math.pi / 2
end
else
return math.atan(y / x) + (x < 0 and math.pi or 0)
end
end
calc_methods["atan2"] = atan2
methods_desc["atan2"] = "返回以弧度为单位的点(x,y)相对于x轴的逆时针角度"
-- 将角度从弧度转换为度
local function deg(x)
return math.deg(x)
end
calc_methods["deg"] = deg
methods_desc["deg"] = "弧度转换为角度"
-- 将角度从度转换为弧度
local function rad(x)
return math.rad(x)
end
calc_methods["rad"] = rad
methods_desc["rad"] = "角度转换为弧度"
-- 返回 x*2^y
local function ldexp(x, y)
return x * 2 ^ y
end
calc_methods["ldexp"] = ldexp
methods_desc["ldexp"] = "返回 x*2^y"
-- 返回 e^x
local function exp(x)
-- 检查参数正确性
if type(x) ~= "number" then
return "参数必须是数字"
end
return math.exp(x)
end
calc_methods["exp"] = exp
methods_desc["exp"] = "返回 e^x"
-- 计算复数的平方根
local function sqrt(...)
local data = {...}
local n = #data
local a,b
if n == 0 then
return "请输入至少一个数"
elseif n > 2 then
return "参数数量不能超过2个"
end
-- 检查参数正确性
for i = 1, n do
if type(data[i]) ~= "number" then
return "参数必须是数字"
end
end
if n == 1 then
a = data[1]
b = 0
elseif n == 2 then
a = data[1]
b = data[2]
end
local t1 = (math.sqrt(a ^ 2 + b ^ 2) + a) / 2
local t2 = (math.sqrt(a ^ 2 + b ^ 2) - a) / 2
local x1, x2, y1, y2
x1 = fn(math.sqrt(t1))
x2 = fn(-math.sqrt(t1))
y1 = fn(math.sqrt(t2))
y2 = fn(-math.sqrt(t2))
if a == 0 and b == 0 then
return 0
elseif a ~= 0 and b == 0 then
if a > 0 then
return x1 .. " , " .. x2
else
return y1 .. "i" .. " , " .. y2 .. "i"
end
elseif b ~= 0 then
if b > 0 then
return x1 .. "+" .. y1 .. "i" .. " , " .. x2 .. "-" .. -y2 .. "i"
else
return x1 .. "-" .. -y2 .. "i" .. " , " .. x2 .. "+" .. y1 .. "i"
end
end
end
calc_methods["sqrt"] = sqrt
methods_desc["sqrt"] = "计算复数的平方根"
-- 计算正数的算术平方根
local function msq(x)
-- 检查参数正确性
if type(x) ~= "number" then
return "参数必须是数字"
end
if x < 0 then
return "参数必须是非负数"
end
return fn(math.sqrt(x))
end
calc_methods["msq"] = msq
methods_desc["msq"] = "计算正数的算术平方根"
-- x为底的对数 log(10, 100) = log(100) / log(10) = 2
local function log(x, y)
-- 不能为负数或0
if x <= 0 or y <= 0 then
return nil
end
return math.log(y) / math.log(x)
end
calc_methods["log"] = log
methods_desc["log"] = "x作为底数的对数"
-- 自然数e为底的对数
local function loge(x)
-- 不能为负数或0
if x <= 0 then
return nil
end
return math.log(x)
end
calc_methods["loge"] = loge
methods_desc["loge"] = "e作为底数的对数"
-- 10为底的对数
local function logt(x)
-- 不能为负数或0
if x <= 0 then
return nil
end
return math.log(x) / math.log(10)
end
calc_methods["logt"] = logt
methods_desc["logt"] = "10作为底数的对数"
-- 平均值
local function avg(...)
local data, n, sum
data = { ... }
n = #data
sum = 0
-- 样本数量不能为0
if n == 0 then
return nil
end
-- 计算总和
for _, value in ipairs(data) do
sum = sum + value
end
return fn(sum / n)
end
calc_methods["avg"] = avg
methods_desc["avg"] = "平均值"
-- 方差
local function variance(...)
local data, n, sum, mean, sum_squared_diff
data = { ... }
n = #data
sum = 0
sum_squared_diff = 0
-- 样本数量不能为0
if n == 0 then
return nil
end
-- 计算均值
for _, value in ipairs(data) do
sum = sum + value
end
mean = sum / n
-- 计算方差
for _, value in ipairs(data) do
sum_squared_diff = sum_squared_diff + (value - mean) ^ 2
end
return fn(sum_squared_diff / n)
end
calc_methods["var"] = variance
methods_desc["var"] = "方差"
-- 阶乘
local function factorial(x)
-- 不能为负数
if x < 0 then
return nil
elseif x == 0 or x == 1 then
return 1
end
local result = 1
for i = 1, x do
result = result * i
end
return fn(result)
end
calc_methods["fact"] = factorial
methods_desc["fact"] = "阶乘"
-- 计算行列式
local function hls(...)
local args, n1, sqrt_n, matrix, index, side_length
args = { ... }
n1 = #args
sqrt_n = math.sqrt(n1)
-- 判断n1是否为完全平方数如果是则将输入的元素重新排列成一个方阵
if sqrt_n == math.floor(sqrt_n) then
matrix = {}
index = 1
side_length = math.floor(sqrt_n)
for i = 1, side_length do
matrix[i] = {}
for j = 1, side_length do
matrix[i][j] = args[index]
index = index + 1
end
end
else
return "给出的元素不能组成一个方阵。"
end
-- 递归计算行列式的函数
local function determinant(matrix)
local n, det, sign, row, sub_matrix
n = #matrix
det = 0
-- 二阶行列式的边界条件
if n == 2 then
return matrix[1][1] * matrix[2][2] - matrix[1][2] * matrix[2][1]
end
-- 递归计算行列式
for j = 1, n do
sub_matrix = {}
for i = 2, n do
row = {}
for k = 1, n do
if k ~= j then
table.insert(row, matrix[i][k])
end
end
table.insert(sub_matrix, row)
end
sign = (-1) ^ (1 + j)
det = det + sign * matrix[1][j] * determinant(sub_matrix)
end
return fn(det)
end
return determinant(matrix)
end
calc_methods["hls"] = hls
methods_desc["hls"] = "计算行列式"
-- 取余函数
local function remainder(x, y)
-- 使用math.fmod函数计算余数
local result = math.fmod(x, y)
-- 如果x是负数math.fmod会返回负数需要调整为正数
if result < 0 then
result = result + y
end
return fn(result)
end
calc_methods["mod"] = remainder
methods_desc["mod"] = "求余函数"
-- 连续自然数平方和(从1开始)
local function sum_of_squares(n)
-- 检查参数
if type(n) ~= "number" or n < 1 or n ~= floor(n) then
return "错误:参数必须为正整数"
end
-- 计算平方和
local result = n * (n + 1) * (2 * n + 1) / 6
return fn(result)
end
calc_methods["sq"] = sum_of_squares
methods_desc["sq"] = "连续自然数平方和(从1开始)"
-- 连续自然数立方和(从1开始)
local function sum_of_cubes(n)
-- 检查参数
if type(n) ~= "number" or n < 1 or n ~= floor(n) then
return "错误:参数必须为正整数"
end
-- 计算立方和
local result = (n * (n + 1)) ^ 2 / 4
return fn(result)
end
calc_methods["cb"] = sum_of_cubes
methods_desc["cb"] = "连续自然数立方和(从1开始)"
-- 连续自然数4次方之和(从1开始)
local function sum_of_fourth_powers(n)
-- 检查参数
if type(n) ~= "number" or n < 1 or n ~= floor(n) then
return "错误:参数必须为正整数"
end
-- 计算4次方和
local result = n * (n + 1) * (2 * n + 1) * (3 * n ^ 2 + 3 * n - 1) / 30
return fn(result)
end
calc_methods["fp"] = sum_of_fourth_powers
methods_desc["fp"] = "连续自然数4次方之和(从1开始)"
-- 前n个奇数的平方和
local function sum_of_odd_squares(n)
-- 检查参数
if type(n) ~= "number" or n < 1 or n ~= floor(n) then
return "错误:参数必须为正整数"
end
-- 计算平方和
local result = n * (4 * n ^ 2 - 1) / 3
return fn(result)
end
calc_methods["osq"] = sum_of_odd_squares
methods_desc["osq"] = "前n个奇数的平方和"
-- 前n个偶数的平方和
local function sum_of_even_squares(n)
-- 检查参数
if type(n) ~= "number" or n < 1 or n ~= floor(n) then
return "错误:参数必须为正整数"
end
-- 计算平方和
local result = 2 * n * (n + 1) * (2 * n + 1) / 3
return fn(result)
end
calc_methods["esq"] = sum_of_even_squares
methods_desc["esq"] = "前n个偶数的平方和"
-- 前n个奇数的立方和
local function sum_of_odd_cubes(n)
-- 检查参数
if type(n) ~= "number" or n < 1 or n ~= floor(n) then
return "错误:参数必须为正整数"
end
-- 计算立方和
local result = n ^ 2 * (2 * n ^ 2 - 1)
return fn(result)
end
calc_methods["ocb"] = sum_of_odd_cubes
methods_desc["ocb"] = "前n个奇数的立方和"
-- 前n个偶数的立方和
local function sum_of_even_cubes(n)
-- 检查参数
if type(n) ~= "number" or n < 1 or n ~= floor(n) then
return "错误:参数必须为正整数"
end
-- 计算立方和
local result = 2 * (n * (n + 1)) ^ 2
return fn(result)
end
calc_methods["ecb"] = sum_of_even_cubes
methods_desc["ecb"] = "前n个偶数的立方和"
-- 前n个奇数的4次方之和
local function sum_of_odd_fourth_powers(n)
-- 检查参数
if type(n) ~= "number" or n < 1 or n ~= floor(n) then
return "错误:参数必须为正整数"
end
-- 计算4次方和
local result = (48 * n ^ 5 - 40 * n ^ 3 + 7 * n) / 15
return fn(result)
end
calc_methods["ofp"] = sum_of_odd_fourth_powers
methods_desc["ofp"] = "前n个奇数的4次方之和"
-- 前n个偶数的4次方之和
local function sum_of_even_fourth_powers(n)
-- 检查参数
if type(n) ~= "number" or n < 1 or n ~= floor(n) then
return "错误:参数必须为正整数"
end
-- 计算4次方和
local result = 8 * n * (n + 1) * (2 * n + 1) * (3 * n ^ 2 + 3 * n - 1) / 15
return fn(result)
end
calc_methods["efp"] = sum_of_even_fourth_powers
methods_desc["efp"] = "前n个偶数的4次方之和"
-- 圆的标准方程的表达式优化
local function CircleStandardEquation(h, k, r_squared)
local standardEquation
if h == 0 then
if k > 0 then
standardEquation = "x²+(y-" .. k .. ")²=" .. r_squared
elseif k == 0 then
standardEquation = "x²+y²=" .. r_squared
else
standardEquation = "x²+(y+" .. -k .. ")²=" .. r_squared
end
elseif k == 0 then
if h > 0 then
standardEquation = "(x-" .. h .. ")²+y²=" .. r_squared
elseif h == 0 then
standardEquation = "x²+y²=" .. r_squared
else
standardEquation = "(x+" .. -h .. ")²+y²=" .. r_squared
end
else
if h > 0 and k > 0 then
standardEquation = "(x-" .. h .. ")²+(y-" .. k .. ")²=" .. r_squared
elseif h > 0 and k < 0 then
standardEquation = "(x-" .. h .. ")²+(y+" .. -k .. ")²=" .. r_squared
elseif h < 0 and k > 0 then
standardEquation = "(x+" .. -h .. ")²+(y-" .. k .. ")²=" .. r_squared
else
standardEquation = "(x+" .. -h .. ")²+(y+" .. -k .. ")²=" .. r_squared
end
end
return standardEquation
end
-- 圆的一般方程表达式优化
local function CircleGeneralEquation(D, E, F)
local generalEquation = "x²+y²"
-- 处理D项
if D ~= 0 then
if D == -1 then
generalEquation = generalEquation .. "-x"
elseif D == 1 then
generalEquation = generalEquation .. "+x"
elseif D > 0 then
generalEquation = generalEquation .. "+" .. D .. "x"
else
generalEquation = generalEquation .. "-" .. -D .. "x"
end
end
-- 处理E项
if E ~= 0 then
if E == -1 then
generalEquation = generalEquation .. "-y"
elseif E == 1 then
generalEquation = generalEquation .. "+y"
elseif E > 0 then
generalEquation = generalEquation .. "+" .. E .. "y"
else
generalEquation = generalEquation .. "-" .. -E .. "y"
end
end
-- 处理F项
if F ~= 0 then
if F > 0 then
generalEquation = generalEquation .. "+" .. F .. "=0"
else
generalEquation = generalEquation .. "-" .. -F .. "=0"
end
end
return generalEquation
end
-- 直线方程(斜截式)表达式优化
local function LineEquation(x1, y1, k)
local equation, b
-- 特殊情况
if k == nil then
return "x=" .. x1
else
equation = "y="
end
if k == 0 then
equation = equation .. y1
return equation
end
-- 计算截距b
b = fn(y1 - k * x1)
-- 优化k的表示
if k == -1 then
equation = equation .. "-x"
elseif k == 1 then
equation = equation .. "x"
else
if k > 0 then
equation = equation .. k .. "x"
else
equation = equation .. "-" .. -k .. "x"
end
end
-- 优化b的表示
if b ~= 0 then
if b > 0 then
equation = equation .. "+" .. b
else
equation = equation .. "-" .. -b
end
end
return equation
end
-- 直线方程(一般式)表达式优化
local function LineGeneralEquation(A, B, C)
-- 检查参数正确性
if A == 0 and B == 0 then
return "错误直线方程系数A和B不能同时为0"
end
-- 求最大公约数,简化系数
local s, result
s = gcd_multiple(math.abs(A), math.abs(B), math.abs(C))
if A < 0 then
A = -A
B = -B
C = -C
end
A = fn(A / s)
B = fn(B / s)
C = fn(C / s)
if A ~= 0 and B == 0 and C == 0 then
result = "x=0"
end
if A ~= 0 and B == 0 and C ~= 0 then
result = "x=" .. fn(-C / A)
end
if A == 0 and B ~= 0 and C == 0 then
result = "y=0"
end
if A == 0 and B ~= 0 and C ~= 0 then
result = "y=" .. fn(-C / B)
end
if A ~= 0 and B ~= 0 then
if A == 1 then
result = "x"
else
result = A .. "x"
end
if B == 1 then
result = result .. "+y"
elseif B == -1 then
result = result .. "-y"
elseif B > 0 then
result = result .. "+" .. B .. "y"
else
result = result .. "-" .. -B .. "y"
end
if C ~= 0 then
if C > 0 then
result = result .. "+" .. C .. "=0"
else
result = result .. "-" .. -C .. "=0"
end
else
result = result .. "=0"
end
end
return result
end
-- 二次函数表达式优化
local function QuadraticEquation(a, b, c)
local result = "y="
-- 格式化a的值
if a ~= 0 then
if a == 1 then
result = result .. ""
elseif a == -1 then
result = result .. "-x²"
else
result = result .. a .. ""
end
end
-- 格式化b的值
if b ~= 0 then
if b == 1 then
result = result .. "+x"
elseif b == -1 then
result = result .. "-x"
elseif b > 0 then
result = result .. "+" .. b .. "x"
else
result = result .. "-" .. -b .. "x"
end
end
-- 格式化c的值
if c ~= 0 then
if c > 0 then
result = result .. "+" .. c
else
result = result .. "-" .. -c
end
end
return result
end
-- 已知正多边形边数n和边长a计算正多边形面积
local function calculateRegularPolygonArea(n, a)
-- 检查参数正确性
if type(n) ~= "number" or type(a) ~= "number" or n ~= floor(n) or n < 1 or a <= 0 then
return "错误边数n必须为正整数边长a必须为正数"
end
-- 计算正多边形的面积
local s = (n * a ^ 2) / (4 * math.tan(math.pi / n))
return fn(s)
end
calc_methods["zdbx"] = calculateRegularPolygonArea
methods_desc["zdbx"] = "已知边数n与边长a计算正多边形面积"
-- 已知等比数列的首项a₁公比q求指定的前n项和
local function geometricSeriesSum(a1, q, n)
-- 检查参数正确性
if type(a1) ~= "number" or type(q) ~= "number" or type(n) ~= "number" or n ~= floor(n) or n < 1 then
return "错误a₁、q、n必须为数字且n是正整数"
end
-- 计算前n项和
if a1 == 0 then
return 0
elseif q == 0 and a1 ~= 0 then
return a1
elseif q == 1 then
return a1 * n
else
local s = a1 * (1 - q ^ n) / (1 - q)
return fn(s)
end
end
calc_methods["dbsl"] = geometricSeriesSum
methods_desc["dbsl"] = "已知等比数列的首项a₁公比q求指定的前n项和"
-- 已知等差数列的首项a₁公差d求指定的前n项和
local function ArithmeticSeriesSum(a1, d, n)
-- 检查参数正确性
if type(a1) ~= "number" or type(d) ~= "number" or type(n) ~= "number" or n ~= floor(n) or n < 1 then
return "错误a₁、d、n必须为数字且n是正整数"
end
-- 计算前n项和
if a1 == 0 and d == 0 then
return 0
elseif a1 ~= 0 and d == 0 then
return a1 * n
else
local s = n * a1 + n * (n - 1) * d / 2
return fn(s)
end
end
calc_methods["dcsl"] = ArithmeticSeriesSum
methods_desc["dcsl"] = "已知等差数列的首项a₁公差d求指定的前n项和"
-- 已知数列中任意两项aᵢ、aₖ求通项公式
-- 对应项数分别为i、k
-- b=0为等差数列b=1为等比数列
local function findSequenceFormula(i, ai, k, ak, b)
-- 检查参数正确性
if type(i) ~= "number" or i ~= floor(i) or i < 1 or type(k) ~= "number" or k ~= floor(k) or k < 1 then
return "错误i 和 k 必须是正整数"
end
if ai == ak and i == k then
return "错误aᵢ、aₖ 和对应的项数不能同时相等"
elseif ai ~= ak and i == k then
return "错误:同一项数对应不同的项值"
end
-- 计算等差数列的通项公式
local function arithmeticSequence(i, ai, k, ak)
local d, a1, s
d = fn((ak - ai) / (k - i))
a1 = ai - (i - 1) * d
s = fn(a1 - d)
if d == 0 then
return "aₙ=" .. a1
elseif d == 1 then
if s == 0 then
return "aₙ=n"
elseif s > 0 then
return "aₙ=n+" .. s
else
return "aₙ=n-" .. -s
end
elseif d == -1 then
if s == 0 then
return "aₙ=-n"
elseif s > 0 then
return "aₙ=-n+" .. s
else
return "aₙ=-n-" .. -s
end
else
if s == 0 then
return "aₙ=" .. d .. "n"
elseif s > 0 then
return "aₙ=" .. d .. "n+" .. s
else
return "aₙ=" .. d .. "n-" .. -s
end
end
end
-- 计算等比数列的通项公式
local function geometricSequence(i, ai, k, ak)
if ai == 0 or ak == 0 then
return "错误等比数列中不能有0项"
end
local s, q, n, a1
s = fn(ak / ai)
n = fn(k - i)
if s < 0 and n % 2 == 0 then
return "无法求解通项公式"
end
q = fn(nth_root(s, n))
a1 = fn(ai / (q ^ (i - 1)))
if a1 == q then
if q == 1 then
return "aₙ=" .. q
elseif q > 0 then
return "aₙ=" .. q .. ""
elseif q < 0 then
return "aₙ=(" .. q .. ")ⁿ"
end
elseif a1 == -q then
if q == 1 then
return "aₙ=-" .. q
elseif q == -1 then
return "aₙ=(" .. q .. ")ⁿ⁻¹"
elseif q > 0 then
return "aₙ=-" .. q .. ""
else
return "aₙ=-(" .. q .. ")ⁿ"
end
else
if q > 0 then
if a1 == 1 then
return "aₙ=" .. q .. "ⁿ⁻¹"
elseif a1 == -1 then
return "aₙ=-" .. q .. "ⁿ⁻¹"
else
return "aₙ=" .. a1 .. "×" .. q .. "ⁿ⁻¹"
end
else
if a1 == 1 then
return "aₙ=(" .. q .. ")ⁿ⁻¹"
elseif a1 == -1 then
return "aₙ=-(" .. q .. ")ⁿ⁻¹"
else
return "aₙ=" .. a1 .. "×(" .. q .. ")ⁿ⁻¹"
end
end
end
end
-- 根据b值返回通项公式
if b == 0 then
return arithmeticSequence(i, ai, k, ak)
elseif b == 1 then
return geometricSequence(i, ai, k, ak)
else
return "错误参数b必须是0或1"
end
end
calc_methods["tx"] = findSequenceFormula
methods_desc["tx"] = "已知数列的任意两项aᵢ、aₖ及对应的项数i、k求其通项公式"
-- 已知圆心坐标(h,k)和半径r求圆的标准方程和一般方程
local function CircleEquationsxr(h, k, r)
-- 检查半径是否为正数
if r <= 0 then
return "错误半径必须大于0"
end
-- 圆的标准方程
local r_squared, se, ge, D, E, F
r_squared = fn(r ^ 2)
se = CircleStandardEquation(h, k, r_squared)
-- 圆的一般方程
D = fn(-2 * h)
E = fn(-2 * k)
F = fn(h ^ 2 + k ^ 2 - r ^ 2)
ge = CircleGeneralEquation(D, E, F)
-- 返回两个方程
return "标准方程: " .. se .. "\n一般方程: " .. ge
end
calc_methods["cexr"] = CircleEquationsxr
methods_desc["cexr"] = "已知圆心坐标和半径求圆的方程"
-- 已知圆心坐标(h,k)和圆上不同两点(x₁,y₁),(x₂,y₂),求圆的标准方程和一般方程
local function CircleEquationsxl(h, k, x1, y1, x2, y2)
-- 检查三个坐标中是否有任意两个点坐标完全相同
if (x1 == x2 and y1 == y2) or (x1 == h and y1 == k) or (x2 == h and y2 == k) then
return "错误:三个坐标中不能有任意两个点坐标完全相同"
end
local distance1, distance2, r, r_squared, se, ge, D, E, F
-- 计算两点到圆心的距离,并检查是否相等
distance1 = math.sqrt((x1 - h) ^ 2 + (y1 - k) ^ 2)
distance2 = math.sqrt((x2 - h) ^ 2 + (y2 - k) ^ 2)
if distance1 ~= distance2 then
return "错误:给定的圆心坐标和两个点无法构成圆"
end
-- 圆的标准方程
r = distance1
r_squared = fn(r ^ 2)
se = CircleStandardEquation(h, k, r_squared)
-- 圆的一般方程
D = fn(-2 * h)
E = fn(-2 * k)
F = fn(h ^ 2 + k ^ 2 - r_squared)
ge = CircleGeneralEquation(D, E, F)
-- 返回两个方程
return "标准方程: " .. se .. "\n一般方程: " .. ge
end
calc_methods["cexl"] = CircleEquationsxl
methods_desc["cexl"] = "已知圆心和圆上不同两点的坐标求圆方程"
-- 已知不共线的三点(x₁,y₁)(x₂,y₂)(x₃,y₃),求过它们的圆的方程
local function CircleEquationssd(x1, y1, x2, y2, x3, y3)
local determinant, A, B, detA, detAD, detAE, detAF, D, E, F, ge, se, r_squared, h, k
-- 检查三个点是否共线
determinant = x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)
if determinant == 0 then
return "错误:三个点共线或重合,无法构成圆"
end
-- 构建系数矩阵A和常数矩阵B
A = {
{ x1, y1, 1 },
{ x2, y2, 1 },
{ x3, y3, 1 }
}
B = {
(-x1 ^ 2 - y1 ^ 2),
(-x2 ^ 2 - y2 ^ 2),
(-x3 ^ 2 - y3 ^ 2)
}
-- 计算系数矩阵A的行列式detA
detA = hls(A[1][1], A[1][2], A[1][3], A[2][1], A[2][2], A[2][3], A[3][1], A[3][2], A[3][3])
-- 计算D、E、F的行列式
detAD = hls(B[1], A[1][2], A[1][3], B[2], A[2][2], A[2][3], B[3], A[3][2], A[3][3])
detAE = hls(A[1][1], B[1], A[1][3], A[2][1], B[2], A[2][3], A[3][1], B[3], A[3][3])
detAF = hls(A[1][1], A[1][2], B[1], A[2][1], A[2][2], B[2], A[3][1], A[3][2], B[3])
-- 计算系数D、E、F
D = fn(detAD / detA)
E = fn(detAE / detA)
F = fn(detAF / detA)
-- 圆的一般方程
ge = CircleGeneralEquation(D, E, F)
-- 圆的标准方程
h = fn(-D / 2)
k = fn(-E / 2)
r_squared = fn(h ^ 2 + k ^ 2 - F)
se = CircleStandardEquation(h, k, r_squared)
-- 返回两个方程
return "标准方程: " .. se .. "\n一般方程: " .. ge
end
calc_methods["cesd"] = CircleEquationssd
methods_desc["cesd"] = "已知圆上不同三点的坐标,求圆方程"
-- 求解一元一次方程:ax+b=0
local function solveLinearEquation(a, b)
-- 检查a是否为0因为如果a为0方程将不再是一元一次方程
if a == 0 then
if b == 0 then
return "方程有无数解"
else
return "方程无解"
end
else
-- 计算x的值
local x = fn(-b / a)
return "x=" .. x
end
end
calc_methods["yyyc"] = solveLinearEquation
methods_desc["yyyc"] = "求解一元一次方程"
-- 求解二元一次方程组ax+by=ecx+dy=f
local function solveLinearSystem(a, b, c, d, e, f)
local D, x, y
-- 计算行列式D
D = a * d - b * c
-- 检查方程组是否有解
if D == 0 then
if (a * f - c * e) == 0 and (b * e - d * f) == 0 then
return "方程组有无穷多解"
else
return "方程组无解"
end
end
-- 计算x和y
x = fn((d * e - b * f) / D)
y = fn((a * f - c * e) / D)
-- 返回解的字符串表示
return "x=" .. x .. "\ny=" .. y
end
calc_methods["eyyc"] = solveLinearSystem
methods_desc["eyyc"] = "求解二元一次方程组ax+by=ecx+dy=f"
-- 点斜法求解一次函数解析式
-- 定义函数输入斜率k和点的坐标(x₁, y₁)
local function pointSlopeForm(k, x1, y1)
local le = LineEquation(x1, y1, k)
return "直线方程: " .. le
end
calc_methods["dxf"] = pointSlopeForm
methods_desc["dxf"] = "点斜法求解一次函数解析式"
-- 两点法求解一次函数解析式
-- 定义函数,输入两点坐标(x₁, y₁)、(x₂,y₂)
local function twoPointsForm(x1, y1, x2, y2)
-- 检查两点是否相同
if x1 == x2 and y1 == y2 then
return "错误:两点坐标完全相同,无法确定直线方程"
end
local k, le
-- 计算斜率k
if x1 == x2 then
k = nil
else
k = (y2 - y1) / (x2 - x1)
k = fn(k)
end
le = LineEquation(x1, y1, k)
return "直线方程: " .. le
end
calc_methods["ldf"] = twoPointsForm
methods_desc["ldf"] = "两点法求解一次函数解析式"
-- 求解一元二次方程ax²+bx+c=0
local function solveQuadraticEquation(a, b, c)
-- 检查参数正确性
if type(a) ~= "number" or type(b) ~= "number" or type(c) ~= "number" then
return "错误:系数必须是数字"
end
if a == 0 then
return "错误二次项系数不能为0"
end
local Delta, x1, x2, P, Q
Delta = b ^ 2 - 4 * a * c
P = fn(-b / (2 * a))
if Delta == 0 then
x1 = P
return "x₁=x₂=" .. x1
elseif Delta > 0 then
Q = fn(math.sqrt(Delta) / (2 * a))
x1 = P + Q
x2 = P - Q
else
Q = fn(math.sqrt(-Delta) / (2 * a))
if P == 0 then
if Q == 1 then
x1 = "i"
x2 = "-i"
elseif Q == -1 then
x1 = "-i"
x2 = "i"
else
x1 = Q .. "i"
x2 = -Q .. "i"
end
else
if Q == 1 then
x1 = P .. "+i"
x2 = P .. "-i"
elseif Q == -1 then
x1 = P .. "-i"
x2 = P .. "+i"
elseif Q > 0 then
x1 = P .. "+" .. Q .. "i"
x2 = P .. "-" .. Q .. "i"
else
x1 = P .. "-" .. -Q .. "i"
x2 = P .. "+" .. -Q .. "i"
end
end
end
return "x₁=" .. x1 .. "\nx₂=" .. x2
end
calc_methods["yyec"] = solveQuadraticEquation
methods_desc["yyec"] = "求解一元二次方程"
-- 求解一元三次方程ax³+bx²+cx+d=0
local function solveCubicEquation(a, b, c, d)
-- 检查参数正确性
if type(a) ~= "number" or type(b) ~= "number" or type(c) ~= "number" or type(d) ~= "number" then
return "错误:系数必须是数字"
end
if a == 0 then
return "错误系数a不能为零"
end
-- 计算重根判别式
local A, B, C, Delta
A = b ^ 2 - 3 * a * c
B = b * c - 9 * a * d
C = c ^ 2 - 3 * b * d
-- 计算总判别式
Delta = B ^ 2 - 4 * A * C
-- 根据盛金公式进行求解
-- 情况1A = B = 0方程有一个三重实根
if A == 0 and B == 0 then
local x = fn(-b / (3 * a))
return "x₁=x₂=x₃=" .. x
-- 情况2Delta > 0方程有一个实根和一对共轭虚根
elseif Delta > 0 then
local Y1, Y2, y1, y2, x1, x2, x3, P, Q
Y1 = A * b + 3 * a * (-B + math.sqrt(Delta)) / 2
Y2 = A * b + 3 * a * (-B - math.sqrt(Delta)) / 2
y1 = nth_root(Y1, 3)
y2 = nth_root(Y2, 3)
x1 = fn((-b - y1 - y2) / (3 * a))
P = fn((-b + 0.5 * (y1 + y2)) / (3 * a))
Q = fn((0.5 * math.sqrt(3) * (y1 - y2)) / (3 * a))
if P == 0 then
if Q == 1 then
x2 = "i"
x3 = "-i"
elseif Q == -1 then
x2 = "-i"
x3 = "i"
else
x2 = Q .. "i"
x3 = -Q .. "i"
end
elseif P ~= 0 and Q == 1 then
x2 = P .. "+i"
x3 = P .. "-i"
elseif P ~= 0 and Q == -1 then
x2 = P .. "-i"
x3 = P .. "+i"
elseif P ~= 0 and Q > 0 then
x2 = P .. "+" .. Q .. "i"
x3 = P .. "-" .. Q .. "i"
elseif P ~= 0 and Q < 0 then
x2 = P .. "-" .. -Q .. "i"
x3 = P .. "+" .. -Q .. "i"
end
return "x₁=" .. x1 .. "\nx₂=" .. x2 .. "\nx₃=" .. x3
-- 情况3Delta = 0方程有三个实根其中有一个两重根
elseif Delta == 0 and A ~= 0 then
local K, x1, x2
K = B / A
x1 = fn(-b / a + K)
x2 = fn(-0.5 * K)
return "x₁=" .. x1 .. "\nx₂=x₃=" .. x2
elseif Delta < 0 and A > 0 then
-- 情况4Delta < 0方程有三个不相等的实根
local T, M, S, R, x1, x2, x3
T = (2 * A * b - 3 * a * B) / (2 * math.sqrt(A ^ 3))
M = acos(T)
S = cos(M / 3)
R = sin(M / 3)
x1 = fn((-b - 2 * math.sqrt(A) * S) / (3 * a))
x2 = fn((-b + math.sqrt(A) * (S + math.sqrt(3) * R)) / (3 * a))
x3 = fn((-b + math.sqrt(A) * (S - math.sqrt(3) * R)) / (3 * a))
return "x₁=" .. x1 .. "\nx₂=" .. x2 .. "\nx₃=" .. x3
end
end
calc_methods["yysc1"] = solveCubicEquation
methods_desc["yysc1"] = "求解一元三次方程"
-- 求解一元四次方程ax⁴+bx³+cx²+dx+e=0
local function solveQuarticEquation(a, b, c, d, e)
-- 检查参数正确性
if type(a) ~= "number" or type(b) ~= "number" or type(c) ~= "number" or type(d) ~= "number" or type(e) ~= "number" then
return "错误:系数必须是数字"
end
if a == 0 then
return "错误系数a不能为零"
end
-- 计算重根判别式
local D, E, F, A, B, C, Delta
D = 3 * b ^ 2 - 8 * a * c
E = -b ^ 3 + 4 * a * b * c - 8 * a ^ 2 * d
F = 3 * b ^ 4 + 16 * a ^ 2 * c ^ 2 - 16 * a * b ^ 2 * c + 16 * a ^ 2 * b * d - 64 * a ^ 3 * e
A = D ^ 2 - 3 * F
B = D * F - 9 * E ^ 2
C = F ^ 2 - 3 * D * E ^ 2
-- 计算总判别式
Delta = B ^ 2 - 4 * A * C
-- 符号因子函数
local function sgn(x)
if x == 0 then
return 0
else
return fn(math.abs(x) / x)
end
end
-- 根据天珩公式求解四次方程
-- 情况1:当D=E=F=0时方程有一个四重实根
if D == 0 and E == 0 and F == 0 then
local x
x = fn(-b / (4 * a))
return "x₁=x₂=x₃=x₄=" .. x
end
-- 情况2:当DEF≠0A=B=C=0时方程有四个实根其中有一个三重根
if (D * E * F ~= 0) and (A == 0 and B == 0 and C == 0) then
local x1, x2
x1 = fn((-b * D + 9 * E) / (4 * a * D))
x2 = fn((-b * D - 3 * E) / (4 * a * D))
return "x₁=" .. x1 .. "\nx₂=x₃=x₄=" .. x2
end
-- 情况3:当E=F=0D≠0时方程有两对二重根若D0根为实数若D0根为虚数
if E == 0 and F == 0 and D ~= 0 then
local x1, x2, P, Q
if D > 0 then
x1 = fn((-b + math.sqrt(D)) / (4 * a))
x2 = fn((-b - math.sqrt(D)) / (4 * a))
else
P = fn(-b / (4 * a))
Q = fn(math.sqrt(-D) / (4 * a))
if P == 0 then
if Q == 1 then
x1 = "i"
x2 = "-i"
elseif Q == -1 then
x1 = "-i"
x2 = "i"
else
x1 = Q .. "i"
x2 = -Q .. "i"
end
else
if Q == 1 then
x1 = P .. "+i"
x2 = P .. "-i"
elseif Q == -1 then
x1 = P .. "-i"
x2 = P .. "+i"
elseif Q > 0 then
x1 = P .. "+" .. Q .. "i"
x2 = P .. "-" .. Q .. "i"
else
x1 = P .. "-" .. -Q .. "i"
x2 = P .. "+" .. -Q .. "i"
end
end
end
return "x₁=x₂=" .. x1 .. "\nx₃=x₄=" .. x2
end
-- 情况4:当ABC≠0Δ=0时方程有一对二重实根
-- 若AB0则其余两根为不等实根若AB0则其余两根为共轭虚根
if (A * B * C ~= 0) and (Delta == 0) then
local P, Q, R, x1, x2, x3
P = -b / (4 * a)
Q = 2 * A * E / (4 * a * B)
x1 = fn(P - Q)
if A * B > 0 then
R = math.sqrt(2 * B / A) / (4 * a)
x2 = fn(P + Q + R)
x3 = fn(P + Q - R)
else
R = fn(math.sqrt(-2 * B / A) / (4 * a))
if (P + Q) == 0 then
if R == 1 then
x2 = "i"
x3 = "-i"
elseif R == -1 then
x2 = "-i"
x3 = "i"
else
x2 = R .. "i"
x3 = -R .. "i"
end
else
if R == 1 then
x2 = fn(P + Q) .. "+i"
x3 = fn(P + Q) .. "-i"
elseif R == -1 then
x2 = fn(P + Q) .. "-i"
x3 = fn(P + Q) .. "+i"
elseif R > 0 then
x2 = fn(P + Q) .. "+" .. R .. "i"
x3 = fn(P + Q) .. "-" .. R .. "i"
else
x2 = fn(P + Q) .. "-" .. -R .. "i"
x3 = fn(P + Q) .. "+" .. -R .. "i"
end
end
end
return "x₁=x₂=" .. x1 .. "\nx₃=" .. x2 .. "\nx₄=" .. x3
end
-- 情况5:当Δ>0时方程有两个不等实根和一对共轭虚根
if Delta > 0 then
local z, z1, z2, z3, x1, x2, x3, x4, P, Q, R1, R2
z1 = A * D + 3 * ((-B + math.sqrt(Delta)) / 2)
z2 = A * D + 3 * ((-B - math.sqrt(Delta)) / 2)
z3 = nth_root(z1, 3) + nth_root(z2, 3)
z = D ^ 2 - D * z3 + z3 ^ 2 - 3 * A
P = -b / (4 * a)
Q = sgn(E) * math.sqrt((D + z3) / 3) / (4 * a)
R1 = math.sqrt((2 * D - z3 + 2 * math.sqrt(z)) / 3) / (4 * a)
R2 = fn(math.sqrt((-2 * D + z3 + 2 * math.sqrt(z)) / 3) / (4 * a))
x1 = fn(P + Q + R1)
x2 = fn(P + Q - R1)
if (P - Q) == 0 then
if R2 == 1 then
x3 = "i"
x4 = "-i"
elseif R2 == -1 then
x3 = "-i"
x4 = "i"
else
x3 = R2 .. "i"
x4 = -R2 .. "i"
end
else
if R2 == 1 then
x3 = fn(P - Q) .. "+i"
x4 = fn(P - Q) .. "-i"
elseif R2 == -1 then
x3 = fn(P - Q) .. "-i"
x4 = fn(P - Q) .. "+i"
elseif R2 > 0 then
x3 = fn(P - Q) .. "+" .. R2 .. "i"
x4 = fn(P - Q) .. "-" .. R2 .. "i"
else
x3 = fn(P - Q) .. "-" .. -R2 .. "i"
x4 = fn(P - Q) .. "+" .. -R2 .. "i"
end
end
return "x₁=" .. x1 .. "\nx₂=" .. x2 .. "\nx₃=" .. x3 .. "\nx₄=" .. x4
end
-- 情况6:当Δ<0时若D与F均为正数则方程有四个不等实根否则方程有两对不等共轭虚根
if Delta < 0 then
local T, M, N, O, y1, y2, y3, x1, x2, x3, x4, P, Q1, Q2, Q3
T = (3 * B - 2 * A * D) / (2 * A * math.sqrt(A))
M = acos(T)
N = cos(M / 3)
O = sin(M / 3)
y1 = (D - 2 * math.sqrt(A) * N) / 3
y2 = (D + math.sqrt(A) * (N + math.sqrt(3) * O)) / 3
y3 = (D + math.sqrt(A) * (N - math.sqrt(3) * O)) / 3
-- 情况6.1:若E=0,D>0,F>0,方程有四实根
if E == 0 and D > 0 and F > 0 then
x1 = fn((-b + math.sqrt(D + 2 * math.sqrt(F))) / (4 * a))
x2 = fn((-b - math.sqrt(D + 2 * math.sqrt(F))) / (4 * a))
x3 = fn((-b + math.sqrt(D - 2 * math.sqrt(F))) / (4 * a))
x4 = fn((-b - math.sqrt(D - 2 * math.sqrt(F))) / (4 * a))
-- 情况6.2:若E=0,D<0,F>0,方程有两对共轭虚根
elseif E == 0 and D < 0 and F > 0 then
P = fn(-b / (4 * a))
Q1 = fn(math.sqrt(-D + 2 * math.sqrt(F)) / (4 * a))
Q2 = fn(math.sqrt(-D - 2 * math.sqrt(F)) / (4 * a))
if P == 0 then
if Q1 == 1 then
x1 = "i"
x2 = "-i"
elseif Q1 == -1 then
x1 = "-i"
x2 = "i"
else
x1 = Q1 .. "i"
x2 = -Q1 .. "i"
end
if Q2 == 1 then
x3 = "i"
x4 = "-i"
elseif Q2 == -1 then
x3 = "-i"
x4 = "i"
else
x3 = Q2 .. "i"
x4 = -Q2 .. "i"
end
else
if Q1 == 1 then
x1 = P .. "+i"
x2 = P .. "-i"
elseif Q1 == -1 then
x1 = P .. "-i"
x2 = P .. "+i"
elseif Q1 > 0 then
x1 = P .. "+" .. Q1 .. "i"
x2 = P .. "-" .. Q1 .. "i"
else
x1 = P .. "-" .. -Q1 .. "i"
x2 = P .. "+" .. -Q1 .. "i"
end
if Q2 == 1 then
x3 = P .. "+i"
x4 = P .. "-i"
elseif Q2 == -1 then
x3 = P .. "-i"
x4 = P .. "+i"
elseif Q2 > 0 then
x3 = P .. "+" .. Q2 .. "i"
x4 = P .. "-" .. Q2 .. "i"
else
x3 = P .. "-" .. -Q2 .. "i"
x4 = P .. "+" .. -Q2 .. "i"
end
end
-- 情况6.3:若E=0,F<0,方程有两对共轭虚根
elseif E == 0 and F < 0 then
P = -b / (4 * a)
Q1 = math.sqrt(2 * D + 2 * math.sqrt(A - F)) / (8 * a)
Q2 = fn(math.sqrt(-2 * D + 2 * math.sqrt(A - F)) / (8 * a))
if (P + Q1) == 0 then
if Q2 == 1 then
x1 = "i"
x2 = "-i"
elseif Q2 == -1 then
x1 = "-i"
x2 = "i"
else
x1 = Q2 .. "i"
x2 = -Q2 .. "i"
end
else
if Q2 == 1 then
x1 = fn(P + Q1) .. "+i"
x2 = fn(P + Q1) .. "-i"
elseif Q2 == -1 then
x1 = fn(P + Q1) .. "-i"
x2 = fn(P + Q1) .. "+i"
elseif Q2 > 0 then
x1 = fn(P + Q1) .. "+" .. Q2 .. "i"
x2 = fn(P + Q1) .. "-" .. Q2 .. "i"
else
x1 = fn(P + Q1) .. "-" .. -Q2 .. "i"
x2 = fn(P + Q1) .. "+" .. -Q2 .. "i"
end
end
if (P - Q1) == 0 then
if Q2 == 1 then
x3 = "i"
x4 = "-i"
elseif Q2 == -1 then
x3 = "-i"
x4 = "i"
else
x3 = Q2 .. "i"
x4 = -Q2 .. "i"
end
else
if Q2 == 1 then
x3 = fn(P - Q1) .. "+i"
x4 = fn(P - Q1) .. "-i"
elseif Q2 == -1 then
x3 = fn(P - Q1) .. "-i"
x4 = fn(P - Q1) .. "+i"
elseif Q2 > 0 then
x3 = fn(P - Q1) .. "+" .. Q2 .. "i"
x4 = fn(P - Q1) .. "-" .. Q2 .. "i"
else
x3 = fn(P - Q1) .. "-" .. -Q2 .. "i"
x4 = fn(P - Q1) .. "+" .. -Q2 .. "i"
end
end
-- 情况6.4:若E≠0,当D与F均为正时方程有四实根否则方程有两对共轭虚根
elseif E ~= 0 then
if D > 0 and F > 0 then
P = -b / (4 * a)
Q1 = sgn(E) * math.sqrt(y1) / (4 * a)
Q2 = (math.sqrt(y2) + math.sqrt(y3)) / (4 * a)
Q3 = (math.sqrt(y2) - math.sqrt(y3)) / (4 * a)
x1 = fn(P + Q1 + Q2)
x2 = fn(P + Q1 - Q2)
x3 = fn(P - Q1 + Q3)
x4 = fn(P - Q1 - Q3)
else
P = -b / (4 * a)
Q1 = math.sqrt(y2) / (4 * a)
Q2 = sgn(E) * math.sqrt(-y1) / (4 * a)
Q3 = math.sqrt(-y3) / (4 * a)
if (P - Q1) == 0 then
if (Q2 + Q3) == 1 then
x1 = "i"
x2 = "-i"
elseif (Q2 + Q3) == -1 then
x1 = "-i"
x2 = "i"
else
x1 = fn(Q2 + Q3) .. "i"
x2 = -fn(Q2 + Q3) .. "i"
end
else
if fn(Q2 + Q3) == 1 then
x1 = fn(P - Q1) .. "+i"
x2 = fn(P - Q1) .. "-i"
elseif fn(Q2 + Q3) == -1 then
x1 = fn(P - Q1) .. "-i"
x2 = fn(P - Q1) .. "+i"
elseif fn(Q2 + Q3) > 0 then
x1 = fn(P - Q1) .. "+" .. fn(Q2 + Q3) .. "i"
x2 = fn(P - Q1) .. "-" .. fn(Q2 + Q3) .. "i"
else
x1 = fn(P - Q1) .. "-" .. -fn(Q2 + Q3) .. "i"
x2 = fn(P - Q1) .. "+" .. -fn(Q2 + Q3) .. "i"
end
end
if (P + Q1) == 0 then
if fn(Q2 - Q3) == 1 then
x3 = "i"
x4 = "-i"
elseif fn(Q2 - Q3) == -1 then
x3 = "-i"
x4 = "i"
else
x3 = fn(Q2 - Q3) .. "i"
x4 = -fn(Q2 - Q3) .. "i"
end
else
if fn(Q2 - Q3) == 1 then
x3 = fn(P + Q1) .. "+i"
x4 = fn(P + Q1) .. "-i"
elseif fn(Q2 - Q3) == -1 then
x3 = fn(P + Q1) .. "-i"
x4 = fn(P + Q1) .. "+i"
elseif fn(Q2 - Q3) > 0 then
x3 = fn(P + Q1) .. "+" .. fn(Q2 - Q3) .. "i"
x4 = fn(P + Q1) .. "-" .. fn(Q2 - Q3) .. "i"
else
x3 = fn(P + Q1) .. "-" .. -fn(Q2 - Q3) .. "i"
x4 = fn(P + Q1) .. "+" .. -fn(Q2 - Q3) .. "i"
end
end
end
end
return "x₁=" .. x1 .. "\nx₂=" .. x2 .. "\nx₃=" .. x3 .. "\nx₄=" .. x4
end
end
calc_methods["yysc2"] = solveQuarticEquation
methods_desc["yysc2"] = "求解一元四次方程"
-- 顶点式求解二次函数解析式y=a(x-h)²+k
-- (x₁,y₁)为顶点坐标,(x₂,y₂)为其函数图像上除顶点坐标外任意一点坐标
local function getQuadraticEquationdd(x1, y1, x2, y2)
-- 检查两个点是否相同
if x1 == x2 or y1 == y2 then
return "错误:两个点的横坐标不能相同"
end
local a, b, c, qe
a = fn((y2 - y1) / (x2 - x1) ^ 2)
b = fn(-2 * a * x1)
c = fn(y1 + a * x1 ^ 2)
qe = QuadraticEquation(a, b, c)
return "二次函数解析式为:" .. qe
end
calc_methods["dds"] = getQuadraticEquationdd
methods_desc["dds"] = "顶点式求解二次函数解析式"
-- 一般式求解二次函数解析式
local function getQuadraticEquationy(x1, y1, x2, y2, x3, y3)
local A, B, detA, detAx, detAy, detAz, a, b, c, qe, determinant
-- 检查三个点是否共线
determinant = x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)
if determinant == 0 then
return "错误:三个点共线或重合,无法求解二次函数解析式"
end
-- 构建方程组的系数矩阵和常数矩阵
A = {
{ x1 ^ 2, x1, 1 },
{ x2 ^ 2, x2, 1 },
{ x3 ^ 2, x3, 1 }
}
B = {
(y1),
(y2),
(y3)
}
-- 计算系数矩阵A的行列式detA
detA = hls(A[1][1], A[1][2], A[1][3], A[2][1], A[2][2], A[2][3], A[3][1], A[3][2], A[3][3])
-- 计算行列式detAxdetAydetAz
detAx = hls(B[1], A[1][2], A[1][3], B[2], A[2][2], A[2][3], B[3], A[3][2], A[3][3])
detAy = hls(A[1][1], B[1], A[1][3], A[2][1], B[2], A[2][3], A[3][1], B[3], A[3][3])
detAz = hls(A[1][1], A[1][2], B[1], A[2][1], A[2][2], B[2], A[3][1], A[3][2], B[3])
-- 计算系数abc
a = fn(detAx / detA)
b = fn(detAy / detA)
c = fn(detAz / detA)
qe = QuadraticEquation(a, b, c)
return "二次函数解析式为:" .. qe
end
calc_methods["ybs"] = getQuadraticEquationy
methods_desc["ybs"] = "一般式求解二次函数解析式"
-- 已知三角形的三边a、b、c求三角形面积
local function calculateTriangleArea(a, b, c)
-- 检查是否能构成三角形
if a + b <= c or a + c <= b or b + c <= a then
return "错误:不能构成三角形"
end
local p, s
-- 计算半周长
p = (a + b + c) / 2
-- 使用海伦公式计算面积
s = math.sqrt(p * (p - a) * (p - b) * (p - c))
return fn(s)
end
calc_methods["sjx1"] = calculateTriangleArea
methods_desc["sjx1"] = "已知三角形的三边长a、b、c求三角形面积"
-- 已知三角形的三个顶点坐标(x₁, y₁)(x₂, y₂)(x₃, y₃),求三角形面积
local function calculateTriangleArea2(x1, y1, x2, y2, x3, y3)
-- 检查参数正确性
if type(x1) ~= "number" or type(y1) ~= "number" or type(x2) ~= "number" or type(y2) ~= "number" or type(x3) ~= "number" or type(y3) ~= "number" then
return "错误:参数必须是数字"
end
local determinant, s
determinant = x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)
-- 检查是否能构成三角形
if determinant == 0 then
return "错误:三个点重合或共线,不能构成三角形"
end
-- 计算三角形面积
s = fn(math.abs(determinant / 2))
return s
end
calc_methods["sjx2"] = calculateTriangleArea2
methods_desc["sjx2"] = "已知三角形的三个顶点坐标(x₁,y₁)(x₂,y₂)(x₃,y₃),求三角形面积"
-- 已知一点(x₁, y₁)和直线方程Ax+By+C=0求点到直线的距离和它关于直线的对称点坐标
local function dyzx1(x1, y1, A, B, C)
-- 检查参数正确性
if type(x1) ~= "number" or type(y1) ~= "number" or type(A) ~= "number" or type(B) ~= "number" or type(C) ~= "number" then
return "错误:参数必须是数字"
end
if A == 0 and B == 0 then
return "错误:直线方程的系数不能同时为零"
end
local S, D, s, x, y
-- 判断点是否在直线上
S = A * x1 + B * y1 + C
if S == 0 then
return "点在直线上距离为0无法求解对称点坐标"
end
-- 计算点到直线的距离
D = fn(math.abs(S) / math.sqrt(A ^ 2 + B ^ 2))
-- 计算对称点坐标
s = S / (A ^ 2 + B ^ 2)
x = fn(x1 - 2 * A * s)
y = fn(y1 - 2 * B * s)
return "点到直线距离为" .. D .. "\n点关于直线的对称点坐标为(" .. x .. "," .. y .. ")"
end
calc_methods["dyzx1"] = dyzx1
methods_desc["dyzx1"] = "已知一点坐标(x₁, y₁)和直线方程Ax+By+C=0求点到直线的距离及对称点坐标"
-- 已知两点(x₁, y₁)和(x₂, y₂),求两点间的距离
local function ld1(x1, y1, x2, y2)
-- 检查参数正确性
if type(x1) ~= "number" or type(y1) ~= "number" or type(x2) ~= "number" or type(y2) ~= "number" then
return "错误:参数必须是数字"
end
-- 判断两点是否重合
if x1 == x2 and y1 == y2 then
return "两点重合距离为0"
end
-- 计算两点间的距离
local D = math.sqrt((x2 - x1) ^ 2 + (y2 - y1) ^ 2)
return fn(D)
end
calc_methods["ld1"] = ld1
methods_desc["ld1"] = "已知两点坐标,求两点间的距离"
-- 已知两点(x₁, y₁)和(x₂, y₂),求两点连线的垂直平分线方程
local function ld2(x1, y1, x2, y2)
-- 检查参数正确性
if type(x1) ~= "number" or type(y1) ~= "number" or type(x2) ~= "number" or type(y2) ~= "number" then
return "错误:参数必须是数字"
end
if x1 == x2 and y1 == y2 then
return "错误:两点重合,无法求解垂直平分线方程"
end
local x3, y3, k, kl, se
-- 两点所成线段的中点坐标
x3 = fn((x1 + x2) / 2)
y3 = fn((y1 + y2) / 2)
if x1 == x2 then
k = nil
kl = 0
else
k = (y2 - y1) / (x2 - x1)
if k == 0 then
kl = nil
else
kl = -1 / k
kl = fn(kl)
end
end
se = LineEquation(x3, y3, kl)
return "垂直平分线方程为:" .. se
end
calc_methods["ld2"] = ld2
methods_desc["ld2"] = "已知两点坐标,求两点间线段的垂直平分线方程"
-- 已知两点P(x₁, y₁)和Q(x₂, y₂)求点P绕点Q旋转角度a(角度制)后的P'坐标
-- 逆时针时a为正顺时针时a为负
local function ld3(x1, y1, x2, y2, a)
-- 检查参数正确性
if type(x1) ~= "number" or type(y1) ~= "number" or type(x2) ~= "number" or type(y2) ~= "number" or type(a) ~= "number" then
return "错误:参数必须是数字"
end
-- 计算旋转角度的弧度值
local a1, x, y
a1 = rad(a)
-- 计算旋转后的点坐标
x = fn(x2 + (x1 - x2) * cos(a1) - (y1 - y2) * sin(a1))
y = fn(y2 + (x1 - x2) * sin(a1) + (y1 - y2) * cos(a1))
return "点P(" .. x1 .. "," .. y1 .. ")绕点Q(" .. x2 .. "," .. y2 .. ")旋转" .. a .. "°后的P'坐标为(" .. x .. "," .. y .. ")"
end
calc_methods["ld3"] = ld3
methods_desc["ld3"] = "已知两点P(x₁, y₁)和Q(x₂, y₂)求点P绕点Q旋转角度a(角度制)后的P'坐标"
-- 已知两条直线方程 A₁x+B₁y+C₁=0和 A₂x+B₂y+C₂=0判断它们的位置关系
local function lines_relationship(A1, B1, C1, A2, B2, C2)
-- 参数正确性检查
if (A1 == 0 and B1 == 0) or (A2 == 0 and B2 == 0) then
return "错误:直线方程的系数不能同时为零"
end
local px, ch, D, x, y, k
-- 判断两直线是否平行或重合的条件
px = (A1 * B2 == A2 * B1) and (A1 * C2 ~= A2 * C1)
ch = (A1 * B2 == A2 * B1) and (C1 * B2 == C2 * B1) and (C1 * A2 == C2 * A1)
-- 两直线重合
if ch then
return "两直线重合距离为0"
-- 两直线平行但不重合,计算距离
elseif px then
if B1 ~= B2 then
k = math.max(B1, B2) / math.min(B1, B2)
if B1 < B2 then
A1 = A1 * k
B1 = B1 * k
C1 = C1 * k
else
C2 = C2 * k
end
end
D = fn(math.abs(C2 - C1) / math.sqrt(A1 ^ 2 + B1 ^ 2))
return "两直线平行,距离为" .. D
-- 两直线相交,计算交点坐标
else
x = fn((B1 * C2 - B2 * C1) / (A1 * B2 - A2 * B1))
y = fn((C1 * A2 - C2 * A1) / (A1 * B2 - A2 * B1))
return "两直线相交,交点坐标为(" .. x .. "," .. y .. ")"
end
end
calc_methods["lzx1"] = lines_relationship
methods_desc["lzx1"] = "已知两直线方程A₁x+B₁y+C₁=0和A₂x+B₂y+C₂=0判断它们的位置关系"
-- 已知三角形的三边a、b、c求内切圆半径和外接圆半径
local function triangle_circles(a, b, c)
-- 参数正确性检查
if a <= 0 or b <= 0 or c <= 0 then
return "错误:边长必须为正数"
end
-- 检查能否构成三角形
if a + b <= c or a + c <= b or b + c <= a then
return "错误:给定的边长不能构成三角形"
end
local s, A, r, R
-- 计算半周长
s = (a + b + c) / 2
-- 计算面积
A = math.sqrt(s * (s - a) * (s - b) * (s - c))
-- 计算内切圆半径
r = fn(A / s)
-- 计算外接圆半径
R = fn((a * b * c) / (4 * A))
return "内切圆半径为" .. r .. "\n外接圆半径为" .. R
end
calc_methods["sjxy1"] = triangle_circles
methods_desc["sjxy1"] = "已知三角形三边长,求内切圆半径和外接圆半径"
-- 已知三角形三个顶点坐标(x₁,y₁)(x₂,y₂)(x₃,y₃),求其内切圆半径和外接圆半径
local function triangle_circles_by_points(x1, y1, x2, y2, x3, y3)
-- 参数正确性检查
if type(x1) ~= "number" or type(y1) ~= "number" or type(x2) ~= "number" or type(y2) ~= "number" or type(x3) ~= "number" or type(y3) ~= "number" then
return "错误:参数必须是数字"
end
local a, b, c
-- 检查三个点是否共线
if x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2) == 0 then
return "错误:三个点共线或重合,无法构成三角形"
end
-- 计算三边长
a = ld1(x1, y1, x2, y2)
b = ld1(x2, y2, x3, y3)
c = ld1(x1, y1, x3, y3)
-- 调用已知三边长的函数计算内切圆半径和外接圆半径
return triangle_circles(a, b, c)
end
calc_methods["sjxy2"] = triangle_circles_by_points
methods_desc["sjxy2"] = "已知三角形三个顶点坐标,求内切圆半径和外接圆半径"
-- 已知三角形三个顶点坐标A(x₁,y₁)B(x₂,y₂)C(x₃,y₃),求其“心”的坐标
local function triangle_centers(x1, y1, x2, y2, x3, y3)
-- 参数正确性检查
if type(x1) ~= "number" or type(y1) ~= "number" or type(x2) ~= "number" or type(y2) ~= "number" or type(x3) ~= "number" or type(y3) ~= "number" then
return "错误:参数必须是数字"
end
local determinant, a, b, c, xg, yg, xn, yn, xw, yw, xc, yc, d1, s1, s2
-- 检查三个点是否共线
determinant = x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)
if determinant == 0 then
return "错误:三个点共线或重合,无法构成三角形"
end
-- 计算三边长
a = ld1(x2, y2, x3, y3)
b = ld1(x1, y1, x3, y3)
c = ld1(x1, y1, x2, y2)
-- 计算重心坐标
xg = fn((x1 + x2 + x3) / 3)
yg = fn((y1 + y2 + y3) / 3)
-- 计算内心坐标
xn = fn((a * x1 + b * x2 + c * x3) / (a + b + c))
yn = fn((a * y1 + b * y2 + c * y3) / (a + b + c))
-- 计算外心坐标
d1 = 2 * determinant
xw = fn(((x1 ^ 2 + y1 ^ 2) * (y2 - y3) + (x2 ^ 2 + y2 ^ 2) * (y3 - y1) + (x3 ^ 2 + y3 ^ 2) * (y1 - y2)) / d1)
yw = fn(((x1 ^ 2 + y1 ^ 2) * (x3 - x2) + (x2 ^ 2 + y2 ^ 2) * (x1 - x3) + (x3 ^ 2 + y3 ^ 2) * (x2 - x1)) / d1)
-- 计算垂心坐标
s1 = x1 * (x2 * (y1 - y2) + x3 * (y3 - y1)) + (y2 - y3) * (x2 * x3 + (y1 - y2) * (y1 - y3))
s2 = x1 ^ 2 * (x2 - x3) + x1 * (x3 ^ 2 - x2 ^ 2 + y1 * y2 - y1 * y3) + x2 ^ 2 * x3 -
x2 * (x3 ^ 2 + y1 * y2 - y2 * y3) +
x3 * y3 * (y1 - y2)
xc = fn(s1 / -determinant)
yc = fn(s2 / determinant)
return "重心(" .. xg .. "," .. yg .. ")\n内心(" .. xn .. "," .. yn .. ")\n外心(" .. xw ..
"," .. yw .. ")\n垂心(" .. xc .. "," .. yc .. ")"
end
calc_methods["sjxx"] = triangle_centers
methods_desc["sjxx"] = "已知三角形三个顶点坐标,求其“心”的坐标"
-- 计算排列数
local function permutation(n, r)
-- 参数检查
if type(n) ~= "number" or type(r) ~= "number" then
return "错误:参数必须为数字"
end
if n < 0 or r < 0 or n ~= math.floor(n) or r ~= math.floor(r) then
return "错误:参数必须为非负整数"
end
if r > n then
return "错误:第二个参数不能大于第一个参数"
end
-- 特殊情况处理
if r == 0 then return 1 end
if r == 1 then return n end
-- 创建分子和分母的因数数组
local numerator_factors = {}
local denominator_factors = {}
-- 填充分子因数 (1 到 n)
for i = 1, n do
table.insert(numerator_factors, i)
end
-- 填充分母因数 (1 到 n-r)
for i = 1, n-r do
table.insert(denominator_factors, i)
end
-- 约分过程
for i = 1, #denominator_factors do
local d = denominator_factors[i]
for j = 1, #numerator_factors do
local n = numerator_factors[j]
local gcd_value = gcd(n, d)
if gcd_value > 1 then
numerator_factors[j] = n / gcd_value
denominator_factors[i] = d / gcd_value
d = denominator_factors[i] -- 更新d值
end
end
end
-- 计算最终结果此时分母应全部为1
local result = 1
for _, v in ipairs(numerator_factors) do
result = result * v
end
return result
end
calc_methods["pls"] = permutation
methods_desc["pls"] = "计算排列数"
-- 计算组合数
local function combination(n, r)
-- 参数检查
if type(n) ~= "number" or type(r) ~= "number" then
return "错误:参数必须为数字"
end
if n < 0 or r < 0 or n ~= math.floor(n) or r ~= math.floor(r) then
return "错误:参数必须为非负整数"
end
if r > n then
return "错误:第二个参数不能大于第一个参数"
end
-- 使用组合数性质 C(n,r) = C(n,n-r) 减少计算量
r = math.min(r, n - r)
if r == 0 or r == n then return 1 end
if r == 1 or r == n-1 then return n end
-- 创建分子和分母的因数数组
local numerator_factors = {}
local denominator_factors = {}
-- 填充分子因数 (n-r+1 到 n)
for i = n - r + 1, n do
table.insert(numerator_factors, i)
end
-- 填充分母因数 (1 到 r)
for i = 1, r do
table.insert(denominator_factors, i)
end
-- 约分过程
for i = 1, #denominator_factors do
local d = denominator_factors[i]
for j = 1, #numerator_factors do
local n = numerator_factors[j]
local gcd_value = gcd(n, d)
if gcd_value > 1 then
numerator_factors[j] = n / gcd_value
denominator_factors[i] = d / gcd_value
d = denominator_factors[i] -- 更新d值
end
end
end
-- 计算最终结果此时分母应全部为1
local result = 1
for _, v in ipairs(numerator_factors) do
result = result * v
end
return result
end
calc_methods["zhs"] = combination
methods_desc["zhs"] = "计算组合数"
-- 已知直线l₁:A₁x+B₁y+C₁=0和l₂:A₂x+B₂y+C₂=0求两条直线以彼此为轴的对称直线方程
local function symmetry_line(A1, B1, C1, A2, B2, C2)
-- 检查参数正确性
if type(A1) ~= "number" or type(B1) ~= "number" or type(C1) ~= "number" or type(A2) ~= "number" or type(B2) ~= "number" or type(C2) ~= "number" then
return "错误:参数必须是数字"
end
if (A1 == 0 and B1 == 0) or (A2 == 0 and B2 == 0) then
return "错误:直线方程的系数不能同时为零"
end
-- 计算对称直线方程的系数
local a1, a2, b, A3, B3, C3, A4, B4, C4, ge1, ge2
a1 = A2 ^ 2 + B2 ^ 2
b = 2 * (A1 * A2 + B1 * B2)
A3 = a1 * A1 - b * A2
B3 = a1 * B1 - b * B2
C3 = a1 * C1 - b * C2
a2 = A1 ^ 2 + B1 ^ 2
A4 = a2 * A2 - b * A1
B4 = a2 * B2 - b * B1
C4 = a2 * C2 - b * C1
ge1 = LineGeneralEquation(A3, B3, C3)
ge2 = LineGeneralEquation(A4, B4, C4)
return "直线l₁关于l₂的对称直线l₃的方程为" .. ge1 .. "\n直线l₂关于l₁的对称直线l₄的方程为" .. ge2
end
calc_methods["lzx2"] = symmetry_line
methods_desc["lzx2"] = "已知直线l₁:A₁x+B₁y+C₁=0和l₂:A₂x+B₂y+C₂=0求两条直线以彼此为轴的对称直线方程"
-- 已知一点P(x₁,y₁)和直线l:Ax+By+C=0求直线l关于点P的对称直线l'的方程
local function dyzx2(x1, y1, A, B, C)
-- 检查参数正确性
if type(x1) ~= "number" or type(y1) ~= "number" or type(A) ~= "number" or type(B) ~= "number" or type(C) ~= "number" then
return "错误:参数必须是数字"
end
if A == 0 and B == 0 then
return "直线方程的系数不能同时为零"
end
local A1, B1, C1, ge
-- 计算对称直线方程的系数
A1 = A
B1 = B
C1 = -(2 * A * x1 + 2 * B * y1 + C)
ge = LineGeneralEquation(A1, B1, C1)
return "直线l关于点P的对称直线l'的方程为:" .. ge
end
calc_methods["dyzx2"] = dyzx2
methods_desc["dyzx2"] = "已知一点P(x₁,y₁)和直线l:Ax+By+C=0求直线l关于点P的对称直线l'的方程"
-- 已知两圆标准方程(x-x₁)²+(y-y₁)²=r₁²和(x-x₂)²+(y-y₂)²=r₂²判断它们的位置关系
local function tcr1(x1, y1, r1, x2, y2, r2)
-- 参数正确性检查
if type(x1) ~= "number" or type(y1) ~= "number" or type(r1) ~= "number" or type(x2) ~= "number" or type(y2) ~= "number" or type(r2) ~= "number" then
return "错误:参数必须是数字"
end
if r1 <= 0 or r2 <= 0 then
return "错误:半径必须为正数"
end
-- 特殊情况:两圆重合
if x1 == x2 and y1 == y2 and r1 == r2 then
return "两圆重合"
end
local d, a, h, m, n, xj1, xj2, yj1, yj2, dj, e
-- 计算两圆圆心距
d = fn(math.sqrt((x1 - x2) ^ 2 + (y1 - y2) ^ 2))
-- 判断位置关系
-- 两圆相离
if d > (r1 + r2) then
return "两圆外离,圆心距为" .. d .. ",无交点"
elseif d < math.abs(r1 - r2) then
return "两圆内含,圆心距为" .. d .. ",无交点"
end
-- 两圆相交或相切,先计算相关参数
a = (r1 ^ 2 - r2 ^ 2 + d ^ 2) / (2 * d)
h = math.sqrt(r1 ^ 2 - a ^ 2)
m = (x2 - x1) / d
n = (y2 - y1) / d
-- 计算交点坐标
xj1 = fn(x1 + a * m + h * n)
yj1 = fn(y1 + a * n - h * m)
xj2 = fn(x1 + a * m - h * n)
yj2 = fn(y1 + a * n + h * m)
e = 1e-8
-- 精度控制,防止浮点数误差导致结果不准确
if math.abs(xj1) < e then
xj1 = 0
end
if math.abs(yj1) < e then
yj1 = 0
end
if math.abs(xj2) < e then
xj2 = 0
end
if math.abs(yj2) < e then
yj2 = 0
end
-- 计算相交弦弦长
dj = fn(math.sqrt((xj2 - xj1) ^ 2 + (yj2 - yj1) ^ 2))
-- 判断相切或相交,并给出交点坐标、圆心距和相交弦长
if d == (r1 + r2) then
return "两圆外切,圆心距为" .. d .. "\n交点坐标为(" .. xj1 .. "," .. yj1 .. ")"
elseif d == math.abs(r1 - r2) then
return "两圆内切,圆心距为" .. d .. "\n交点坐标为(" .. xj1 .. "," .. yj1 .. ")"
elseif math.abs(r1 - r2) < d and d < (r1 + r2) then
return "两圆相交,圆心距为" .. d .. "\n交点坐标为(" .. xj1 .. "," .. yj1 .. ")和(" .. xj2 .. "," .. yj2 .. ")\n相交弦弦长为" .. dj
end
end
calc_methods["tcr1"] = tcr1
methods_desc["tcr1"] = "已知两圆标准方程(x-x₁)²+(y-y₁)²=r₁²和(x-x₂)²+(y-y₂)²=r₂²判断它们的位置关系"
-- 已知两圆一般方程x²+y²+D₁x+E₁y+F₁=0和x²+y²+D₂x+E₂y+F₂=0判断它们的位置关系
local function tcr2(D1, E1, F1, D2, E2, F2)
-- 参数正确性检查
if type(D1) ~= "number" or type(E1) ~= "number" or type(F1) ~= "number" or type(D2) ~= "number" or type(E2) ~= "number" or type(F2) ~= "number" then
return "错误:参数必须是数字"
end
local x1, y1, x2, y2, r1, r2
-- 计算两圆圆心,半径,圆心距
x1 = -D1 / 2
y1 = -E1 / 2
x2 = -D2 / 2
y2 = -E2 / 2
r1 = math.sqrt(x1 ^ 2 + y1 ^ 2 - F1)
r2 = math.sqrt(x2 ^ 2 + y2 ^ 2 - F2)
-- 调用函数输出结果
return tcr1(x1, y1, r1, x2, y2, r2)
end
calc_methods["tcr2"] = tcr2
methods_desc["tcr2"] = "已知两圆一般方程x²+y²+D₁x+E₁y+F₁=0和x²+y²+D₂x+E₂y+F₂=0判断它们的位置关系"
-- 求解勾股数
local function ggs(...)
local args = { ... }
local n = #args
if n == 0 then
return "请输入至少一个数"
elseif n > 2 then
return "最多只能输入2个数"
end
local function generateTriplets(a_param)
local results = {}
-- 生成作为直角边的解
if a_param % 2 == 1 then
local c = (a_param ^ 2 - 1) / 2
local d = (a_param ^ 2 + 1) / 2
local triplet = { a_param, c, d }
table.sort(triplet)
table.insert(results, triplet)
else
local c = (a_param ^ 2) / 4 - 1
local d = (a_param ^ 2) / 4 + 1
local triplet = { a_param, c, d }
table.sort(triplet)
table.insert(results, triplet)
end
return results
end
local function findHypotenuseTriplets(m)
local results = {}
local m_squared = m * m
local max_a = math.floor(m / math.sqrt(2))
for a = 1, max_a do
local b_squared = m_squared - a * a
if b_squared < 0 then break end
local b = math.sqrt(b_squared)
if b == math.floor(b) and b > a then
local triplet = { a, b, m }
table.sort(triplet)
table.insert(results, triplet)
end
end
return results
end
local function ggs1(a)
if type(a) ~= "number" or a < 1 or a ~= math.floor(a) then
return "参数必须是正整数"
end
if a % 2 == 1 and a < 3 then
return "输入1个参数时,奇数须大于等于3"
elseif a % 2 == 0 and a < 4 then
return "输入1个参数时,偶数须大于等于4"
end
local results = {}
-- 生成直角边解
local legTriplets = generateTriplets(a)
for _, t in ipairs(legTriplets) do
table.insert(results, t)
end
-- 生成斜边解
local hypoTrplets = findHypotenuseTriplets(a)
for _, t in ipairs(hypoTrplets) do
table.insert(results, t)
end
-- 去重
local seen = {}
local unique = {}
for _, t in ipairs(results) do
local key = table.concat(t, ',')
if not seen[key] then
seen[key] = true
table.insert(unique, t)
end
end
if #unique == 0 then
return "无解"
else
local parts = {}
for _, t in ipairs(unique) do
table.insert(parts, string.format("(%d,%d,%d)", t[1], t[2], t[3]))
end
return "勾股数为: " .. table.concat(parts, "")
end
end
local function ggs2(a, b)
if type(a) ~= "number" or a < 1 or a ~= math.floor(a) or
type(b) ~= "number" or b < 1 or b ~= math.floor(b) then
return "参数必须是正整数"
end
if a == b then
return "两个参数不能相等"
end
local results = {}
-- 两数作为直角边求斜边
local sum_sq = a ^ 2 + b ^ 2
local c = math.sqrt(sum_sq)
if c == math.floor(c) then
local triplet = { a, b, c }
table.sort(triplet)
table.insert(results, triplet)
end
-- 小数作为直角边,大数作为斜边求另一直角边
local sq = math.abs(a ^ 2 - b ^ 2)
local d = math.sqrt(sq)
if d == math.floor(d) then
local triplet = { a, b, d }
table.sort(triplet)
table.insert(results, triplet)
end
-- 作为生成元求三元组
local part1 = math.abs(a ^ 2 - b ^ 2)
local part2 = 2 * a * b
local hypo = a ^ 2 + b ^ 2
local triplet = { part1, part2, hypo }
table.sort(triplet)
table.insert(results, triplet)
-- 去重逻辑
local seen = {}
local unique = {}
for _, t in ipairs(results) do
local key = table.concat(t, ",")
if not seen[key] then
seen[key] = true
table.insert(unique, t)
end
end
if #unique == 0 then
return "无解"
else
local parts = {}
for _, t in ipairs(unique) do
table.insert(parts, string.format("(%d,%d,%d)", t[1], t[2], t[3]))
end
return "勾股数为: " .. table.concat(parts, "")
end
end
return (n == 1) and ggs1(args[1]) or ggs2(args[1], args[2])
end
calc_methods["ggs"] = ggs
methods_desc["ggs"] = "求解勾股数"
-- 批量随机数生成器
-- 参数模式13个参数digits位数、count数量、unique是否唯一0为true/1为false
-- 参数模式24个参数min最小值、max最大值、count数量、unique是否唯一
local function generateRandomNumbers(...)
local args = { ... }
local min, max, count, unique
-- 验证参数数量
if #args ~= 3 and #args ~= 4 then
return "参数数量必须为3或4"
end
-- 解析参数模式
if #args == 3 then
local digits, count_arg, unique_arg = args[1], args[2], args[3]
-- 验证参数类型和范围
if type(digits) ~= "number" or type(count_arg) ~= "number" or type(unique_arg) ~= "number" then
return "位数、数量和唯一性参数必须为数字"
elseif digits < 1 or digits ~= math.floor(digits) then
return "位数必须为正整数"
elseif digits > 18 then
return "位数不能超过18位"
end
min = 10 ^ (digits - 1)
max = 10 ^ digits - 1
if digits == 1 then min = 1 end -- 一位数的特殊情况
count = count_arg
unique = unique_arg
else
min, max, count, unique = args[1], args[2], args[3], args[4]
-- 验证参数合法性
if type(min) ~= "number" or type(max) ~= "number" or type(count) ~= "number" then
return "最小值、最大值和数量必须为数字"
elseif min ~= math.floor(min) or max ~= math.floor(max) then
return "最小值、最大值必须为整数"
end
end
-- 通用参数验证
if min > max then
min, max = max, min -- 自动交换顺序
end
if count < 1 or count ~= math.floor(count) then
return "数量必须为正整数"
elseif unique ~= 0 and unique ~= 1 then
return "控制唯一性的参数必须为0或1"
elseif unique == 0 and count > (max - min + 1) then
return "唯一性要求下,数量不能超过范围大小"
end
-- 存储随机数的表
local result = {}
-- 生成随机数
if unique == 0 then
local used = {} -- 记录已生成的随机数
for i = 1, count do
local num
repeat
num = math.random(min, max)
until not used[num]
used[num] = true
result[i] = num
end
else
-- 非唯一情况,直接填充结果表
for i = 1, count do
result[i] = math.random(min, max)
end
end
-- 格式化输出
local formatted = {}
for i = 1, #result do
if i > 1 and (i - 1) % 10 == 0 then
table.insert(formatted, "\n")
end
table.insert(formatted, tostring(result[i]))
if i < #result and i % 10 ~= 0 then
table.insert(formatted, ",")
end
end
return table.concat(formatted)
end
calc_methods["psjs"] = generateRandomNumbers
methods_desc["psjs"] = "批量随机数"
-- 质因数分解(带优化输出格式)
local function prime_factorization(n)
-- 参数检查与位数限制
if type(n) ~= "number" or n <= 0 or math.floor(n) ~= n then
return "参数必须是正整数"
end
local digits = #tostring(n)
if digits > 18 then
return "数字超限! 最大支持18位数字的质因数分解。"
end
-- 处理特殊情况
if n == 1 then return "1" end
local factors = {}
-- 处理2的因子
while n % 2 == 0 do
factors[2] = (factors[2] or 0) + 1
n = math.floor(n / 2)
end
-- 处理奇数因子
local divisor = 3
local max_divisor = math.floor(math.sqrt(n))
while divisor <= max_divisor and n > 1 do
while n % divisor == 0 do
factors[divisor] = (factors[divisor] or 0) + 1
n = math.floor(n / divisor)
max_divisor = math.floor(math.sqrt(n))
end
divisor = divisor + 2
end
-- 如果n仍然大于1则n本身是一个质数
if n > 1 then
factors[n] = (factors[n] or 0) + 1
end
-- 优化的指数符号表仅包含0-9
local superscript_digits = {
["0"] = "",
["1"] = "¹",
["2"] = "²",
["3"] = "³",
["4"] = "",
["5"] = "",
["6"] = "",
["7"] = "",
["8"] = "",
["9"] = ""
}
-- 转换数字为上标形式(支持任意位数)
local function to_superscript(num)
local s = tostring(num)
local result = ""
for i = 1, #s do
local c = s:sub(i, i)
result = result .. (superscript_digits[c] or c)
end
return result
end
-- 生成输出字符串
local output = {}
for factor, count in pairs(factors) do
local str = tostring(factor)
if count > 1 then
str = str .. to_superscript(count)
end
table.insert(output, str)
end
-- 按质因数从小到大排序
table.sort(output, function(a, b)
local fa = tonumber(a:match("^%d+"))
local fb = tonumber(b:match("^%d+"))
return fa < fb
end)
return table.concat(output, "×")
end
calc_methods["zys"] = prime_factorization
methods_desc["zys"] = "质因数分解"
-- 找质数(欧拉筛法)
local function sieve_of_eratosthenes(n)
if type(n) ~= "number" or n <= 1 or math.floor(n) ~= n then
return "参数必须是大于1的正整数"
end
if n > 26338 then
return "数字超限!"
end
local is_prime = {}
local primes = {}
-- 初始化数组,默认所有数都是质数
for i = 2, n do
is_prime[i] = true
end
-- 欧拉筛法核心逻辑
for i = 2, n do
if is_prime[i] then
table.insert(primes, i)
end
-- 遍历已找到的质数,标记合数
for j = 1, #primes do
local p = primes[j]
local composite = i * p
if composite > n then break end
is_prime[composite] = false
-- 关键优化:确保每个合数只被其最小质因数标记一次
if i % p == 0 then break end
end
end
-- 格式化输出
local output = {}
for i = 1, #primes do
table.insert(output, tostring(primes[i]))
if (i % 10 == 0) or (i == #primes) then
table.insert(output, "\n")
else
table.insert(output, ",")
end
end
-- 如果最后一个元素是换行符,则移除它
if #output > 0 and output[#output] == "\n" then
output[#output] = nil
end
return table.concat(output)
end
calc_methods["zzs"] = sieve_of_eratosthenes
methods_desc["zzs"] = "找质数"
-- 24点计算器含去重逻辑
local function solve24(...)
-- 检查表中是否包含某个值
local function table_contains(tab, val)
for _, value in ipairs(tab) do
if value == val then
return true
end
end
return false
end
-- 生成随机数的函数
local function generate_numbers()
math.randomseed(os.time())
local numbers = {}
local magic_numbers = {} -- 新增:魔术字数组
for i = 1, 4 do
numbers[i] = math.random(1, 13)
-- 生成魔术字1的魔术字固定为1
if numbers[i] == 1 then
magic_numbers[i] = 1
else
local newrd = math.random(1, 40)
-- 确保魔术字不重复
while table_contains(magic_numbers, newrd) do
newrd = math.random(1, 40)
end
magic_numbers[i] = newrd
end
end
-- 如果数字有重复,魔术字也做同样的重复
for i = 1, 4 do
for j = i + 1, 4 do
if numbers[i] == numbers[j] then
magic_numbers[j] = magic_numbers[i]
end
end
end
return numbers, magic_numbers
end
-- 去重用的魔术字解决方案记录
local hash_solutions = {}
local solutions = {}
-- 判断两个数是否接近(处理浮点数精度问题)
local function is_close(a, b)
return math.abs(a - b) < 1e-9
end
-- 基本计算函数
local function compute(a, b, op)
if op == '+' then
return a + b
elseif op == '-' then
return a - b
elseif op == '*' then
return a * b
elseif op == '/' then
if b == 0 then return nil end
return a / b
end
end
-- 计算魔术字
local function compute_magic(a, b, op, magic_a, magic_b)
if op == '+' then
return magic_a + magic_b
elseif op == '-' then
return magic_a - magic_b
elseif op == '*' then
return magic_a * magic_b
elseif op == '/' then
if magic_b == 0 then return 999999999 end -- 避免除以0
return magic_a / magic_b
end
end
-- 排列组合函数
local function permute(t)
local result = {}
local function permute_helper(current, remaining)
if #remaining == 0 then
table.insert(result, { table.unpack(current) })
else
for i = 1, #remaining do
local new_current = { table.unpack(current) }
table.insert(new_current, remaining[i])
local new_remaining = {}
for j = 1, #remaining do
if j ~= i then
table.insert(new_remaining, remaining[j])
end
end
permute_helper(new_current, new_remaining)
end
end
end
permute_helper({}, t)
return result
end
-- 用于添加解决方案并去重
local function add_solution(expr, value, magic_value)
if is_close(value, 24) then
-- 检查魔术字是否已存在
local is_duplicate = false
local replace_index = -1
for i, hash in ipairs(hash_solutions) do
if math.abs(magic_value - hash) / (math.abs(magic_value) + 1e-9) < 1e-3 then
is_duplicate = true
replace_index = i
break
end
end
if not is_duplicate then
-- 新解决方案,添加到列表
table.insert(solutions, expr)
table.insert(hash_solutions, magic_value)
else
-- 检查是否需要替换为更优的解决方案
local need_replace = false
local existing_expr = solutions[replace_index]
-- 比较括号数量
local current_brackets = expr:gsub("[^%(%)]", ""):len()
local existing_brackets = existing_expr:gsub("[^%(%)]", ""):len()
if current_brackets < existing_brackets then
need_replace = true
-- 括号数量相同,比较减号数量
elseif current_brackets == existing_brackets then
local current_minus = expr:gsub("[^-]", ""):len()
local existing_minus = existing_expr:gsub("[^-]", ""):len()
if current_minus < existing_minus then
need_replace = true
-- 减号数量相同,比较除号数量
elseif current_minus == existing_minus then
local current_div = expr:gsub("[^/÷]", ""):len()
local existing_div = existing_expr:gsub("[^/÷]", ""):len()
if current_div < existing_div then
need_replace = true
-- 除号数量相同,比较表达式字典序
elseif current_div == existing_div and expr < existing_expr then
need_replace = true
end
end
end
if need_replace then
solutions[replace_index] = expr
hash_solutions[replace_index] = magic_value
end
end
end
end
-- 核心解决24点问题的函数
local function solve_24_with_magic(numbers, magic_numbers)
local operators = { '+', '-', '*', '/' }
local perms = permute(numbers)
local magic_perms = permute(magic_numbers) -- 魔术字的排列组合
-- 遍历所有数字和魔术字的排列组合
for i, nums in ipairs(perms) do
local magics = magic_perms[i]
if magics then
for _, op1 in ipairs(operators) do
for _, op2 in ipairs(operators) do
for _, op3 in ipairs(operators) do
-- 情况1: ((a op1 b) op2 c) op3 d
local v1 = compute(nums[1], nums[2], op1)
local m1 = compute_magic(nums[1], nums[2], op1, magics[1], magics[2])
if v1 and m1 then
local v2 = compute(v1, nums[3], op2)
local m2 = compute_magic(v1, nums[3], op2, m1, magics[3])
if v2 and m2 then
local v3 = compute(v2, nums[4], op3)
local m3 = compute_magic(v2, nums[4], op3, m2, magics[4])
if v3 and m3 then
local expr = string.format("((%d%s%d)%s%d)%s%d", nums[1], op1, nums[2], op2,
nums[3], op3, nums[4])
add_solution(expr, v3, m3)
end
end
end
-- 情况2: (a op1 (b op2 c)) op3 d
local v1 = compute(nums[2], nums[3], op2)
local m1 = compute_magic(nums[2], nums[3], op2, magics[2], magics[3])
if v1 and m1 then
local v2 = compute(nums[1], v1, op1)
local m2 = compute_magic(nums[1], v1, op1, magics[1], m1)
if v2 and m2 then
local v3 = compute(v2, nums[4], op3)
local m3 = compute_magic(v2, nums[4], op3, m2, magics[4])
if v3 and m3 then
local expr = string.format("(%d%s(%d%s%d))%s%d", nums[1], op1, nums[2], op2,
nums[3], op3, nums[4])
add_solution(expr, v3, m3)
end
end
end
-- 情况3: a op1 ((b op2 c) op3 d)
local v1 = compute(nums[2], nums[3], op2)
local m1 = compute_magic(nums[2], nums[3], op2, magics[2], magics[3])
if v1 and m1 then
local v2 = compute(v1, nums[4], op3)
local m2 = compute_magic(v1, nums[4], op3, m1, magics[4])
if v2 and m2 then
local v3 = compute(nums[1], v2, op1)
local m3 = compute_magic(nums[1], v2, op1, magics[1], m2)
if v3 and m3 then
local expr = string.format("%d%s((%d%s%d)%s%d)", nums[1], op1, nums[2], op2,
nums[3], op3, nums[4])
add_solution(expr, v3, m3)
end
end
end
-- 情况4: a op1 (b op2 (c op3 d))
local v1 = compute(nums[3], nums[4], op3)
local m1 = compute_magic(nums[3], nums[4], op3, magics[3], magics[4])
if v1 and m1 then
local v2 = compute(nums[2], v1, op2)
local m2 = compute_magic(nums[2], v1, op2, magics[2], m1)
if v2 and m2 then
local v3 = compute(nums[1], v2, op1)
local m3 = compute_magic(nums[1], v2, op1, magics[1], m2)
if v3 and m3 then
local expr = string.format("%d%s(%d%s(%d%s%d))", nums[1], op1, nums[2], op2,
nums[3], op3, nums[4])
add_solution(expr, v3, m3)
end
end
end
-- 情况5: (a op1 b) op2 (c op3 d)
local v1 = compute(nums[1], nums[2], op1)
local m1 = compute_magic(nums[1], nums[2], op1, magics[1], magics[2])
local v2 = compute(nums[3], nums[4], op3)
local m2 = compute_magic(nums[3], nums[4], op3, magics[3], magics[4])
if v1 and m1 and v2 and m2 then
local v3 = compute(v1, v2, op2)
local m3 = compute_magic(v1, v2, op2, m1, m2)
if v3 and m3 then
local expr = string.format("(%d%s%d)%s(%d%s%d)", nums[1], op1, nums[2], op2, nums[3],
op3, nums[4])
add_solution(expr, v3, m3)
end
end
end
end
end
end
end
return solutions
end
-- 处理函数参数
local arg = { ... }
if #arg == 0 then
-- 无参数,生成随机数
local numbers, magic_numbers = generate_numbers()
return "生成的随机数: " .. table.concat(numbers, ", ")
elseif #arg == 4 then
-- 检查输入的四个参数是否都在1到13之间且为整数
for i, num in ipairs(arg) do
if type(num) ~= "number" or num < 1 or num > 13 or num ~= math.floor(num) then
return "错误请输入4个1到13之间的整数。"
end
end
-- 为输入的数字生成魔术字
local magic_numbers = {}
for i, num in ipairs(arg) do
if num == 1 then
magic_numbers[i] = 1
else
local newrd = math.random(1, 40)
while table_contains(magic_numbers, newrd) do
newrd = math.random(1, 40)
end
magic_numbers[i] = newrd
end
end
-- 处理数字重复的情况
for i = 1, 4 do
for j = i + 1, 4 do
if arg[i] == arg[j] then
magic_numbers[j] = magic_numbers[i]
end
end
end
-- 求解24点
local solutions = solve_24_with_magic(arg, magic_numbers)
if #solutions == 0 then
return "没有找到解决方案。"
else
return "共找到" .. #solutions .. "种解决方案:\n" .. table.concat(solutions, "\n")
end
else
return "错误请输入4个数字或者不输入参数以生成随机数。"
end
end
calc_methods["tfp"] = solve24
methods_desc["tfp"] = "24点计算器"
-- 单位换算脚本
-- 注意:单位是作为字符串类型参数传入的,所以输入时应加引号(单双均可,但不能混用)
-- 否则会因参数类型错误而无法输出正确结果
local function dwhs(value, from_unit, to_unit)
-- 单位转换系数表
local conversion_factors = {
-- 长度 (相对于米)
ai = 1e-10, -- 埃
nm = 1e-9, -- 纳米
wm = 1e-6, -- 微米
mm = 1e-3, -- 毫米
cm = 0.01, -- 厘米
dm = 0.1, -- 分米
m = 1, -- 米
km = 1e3, -- 千米
li = 500, -- 里
yc = 0.0254, -- 英寸
ft = 0.3048, -- 英尺
mile = 1609.344, -- 英里
nmi = 1852, -- 海里
zhang = 10 / 3, -- 丈
chi = 1 / 3, -- 尺
cun = 1 / 30, -- 寸
fen = 1 / 300, -- 分
-- 面积 (相对于平方米)
mm2 = 1e-6, -- 平方毫米
cm2 = 1e-4, -- 平方厘米
dm2 = 1e-2, -- 平方分米
m2 = 1, -- 平方米
km2 = 1e6, -- 平方千米
pfyl = 2589988.1103, -- 平方英里
hm2 = 1e4, -- 公顷
sq = 2e5 / 3, -- 市顷
acre = 4046.8648, -- 英亩
sm = 2000 / 3, -- 市亩
gm = 100, -- 公亩
-- 体积 (相对于立方米)
wl = 1e-9, -- 微升
mm3 = 1e-9, -- 立方毫米
ml = 1e-6, -- 毫升
cm3 = 1e-6, -- 立方厘米
cl = 1e-5, -- 厘升
dl = 1e-4, -- 分升
l = 1e-3, -- 升
dm3 = 1e-3, -- 立方分米
hl = 0.1, -- 公石
m3 = 1, -- 立方米
ygl = 4.5461e-3, -- 英制加仑
mgl = 3.78541e-3, -- 美制加仑
km3 = 1e9, -- 立方千米
-- 质量 (相对于克)
wg = 1e-6, -- 微克
mg = 1e-3, -- 毫克
g = 1, -- 克
kg = 1e3, -- 千克
t = 1e6, -- 吨
lb = 453.59237, -- 磅
oz = 28.349523125, -- 盎司
ct = 0.2, -- 克拉
gd = 1e5, -- 公担
sd = 5e4, -- 市担
jin = 500, -- 斤
liang = 50, -- 两
qian = 5, -- 钱
dr = 1.771845195, -- 打兰
gr = 0.06479891, -- 格令
}
-- 检查数值有效性
if type(value) ~= "number" or value <= 0 then
return "错误: 第一个参数必须是有效的正数"
end
-- 检查单位有效性
if not conversion_factors[from_unit] then
return "错误: 未知的原单位 '" .. tostring(from_unit) .. "'"
end
if not conversion_factors[to_unit] then
return "错误: 未知的目标单位 '" .. tostring(to_unit) .. "'"
end
-- 将数字转换为上标字符
local function to_superscript(num)
local superscripts = { "", "¹", "²", "³", "", "", "", "", "", "" }
local minus = ""
local str = tostring(num)
local result = ""
-- 处理负号
if str:sub(1, 1) == "-" then
result = minus
str = str:sub(2)
end
-- 移除前导零除非是单独的0
str = str:gsub("^0+(%d)", "%1")
if str == "" then str = "0" end
-- 转换数字
for digit in str:gmatch("%d") do
result = result .. superscripts[tonumber(digit) + 1]
end
return result
end
-- 格式化科学记数法输出为上标形式
local function format_scientific(num)
local formatted = string.format("%.6e", num)
local mantissa, exponent = string.match(formatted, "^(.-)e([%+%-]%d+)$")
mantissa = mantissa:gsub("%.?0+$", ""):gsub("%.$", "")
-- 移除指数前的+号
exponent = exponent:gsub("^%+", "")
return mantissa .. "×10" .. to_superscript(exponent)
end
-- 判断是否应该使用科学计数法
local function should_use_scientific(num)
local abs_num = math.abs(num)
-- 对于大于等于1e5或小于等于1e-3的数字使用科学计数法
if abs_num >= 1e5 or (abs_num <= 1e-3 and abs_num > 0) then
return true
end
-- 检查整数部分位数
local int_part = math.floor(abs_num)
if int_part == 0 then
-- 检查小数部分前导零的数量
local decimal_str = string.format("%.10f", abs_num - int_part)
local leading_zeros = 0
for i = 3, #decimal_str do
if decimal_str:sub(i, i) == "0" then
leading_zeros = leading_zeros + 1
else
break
end
end
return leading_zeros >= 3
else
return (math.log10(int_part) + 1) > 4
end
end
-- 格式化数字输出
local function format_number(num)
if should_use_scientific(num) then
return format_scientific(num)
else
return string.format("%.6f", num):gsub("%.?0+$", ""):gsub("%.$", "")
end
end
-- 执行转换
local result = value * (conversion_factors[from_unit] / conversion_factors[to_unit])
-- 格式化输出
local formatted_result = format_number(result)
-- 显示结果
return formatted_result
end
calc_methods["dwhs"] = dwhs
methods_desc["dwhs"] = "单位换算,支持面积、质量、长度、体积"
-- 数字进制转换
-- 注意在输入有字母的非10进制数时需加上引号单双均可但不能混用
-- 否则无法输出结果
local function convertBase(...)
local args = { ... }
local number, fromBase, toBase
-- 参数数量处理
if #args == 3 then
number, fromBase, toBase = args[1], args[2], args[3]
elseif #args == 2 then
number, toBase = args[1], args[2]
fromBase = 10 -- 默认原进制为十进制
else
return "参数数量必须为2或3"
end
-- 进制合法性检查
if type(fromBase) ~= "number" or type(toBase) ~= "number" then
return "进制必须是数字类型"
end
if fromBase < 2 or fromBase > 36 or toBase < 2 or toBase > 36 then
return "进制范围必须在2到36之间"
end
local number = tostring(number)
-- 检查是否为有效数字格式
local sign = 1
local integerPart, fractionalPart
-- 处理符号
if string.sub(number, 1, 1) == '-' then
sign = -1
number = string.sub(number, 2)
elseif string.sub(number, 1, 1) == '+' then
number = string.sub(number, 2)
end
-- 分离整数和小数部分
local dotPos = string.find(number, '%.')
if dotPos then
integerPart = string.sub(number, 1, dotPos - 1)
fractionalPart = string.sub(number, dotPos + 1)
else
integerPart = number
fractionalPart = ""
end
-- 定义数字字符集
local digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-- 辅助函数:字符转数值
local function charToValue(c)
return string.find(digits, string.upper(c), 1, true) - 1
end
-- 辅助函数:数值转字符
local function valueToChar(v)
return string.sub(digits, v + 1, v + 1)
end
-- 整数部分转换:原进制转十进制
local decimalInteger = 0
for i = 1, #integerPart do
local c = string.sub(integerPart, i, i)
local v = charToValue(c)
if v == -1 or v >= fromBase then
return "数字中包含无效字符或超出原进制范围"
end
decimalInteger = decimalInteger * fromBase + v
end
-- 小数部分转换:原进制转十进制
local decimalFraction = 0
local multiplier = 1 / fromBase
for i = 1, #fractionalPart do
local c = string.sub(fractionalPart, i, i)
local v = charToValue(c)
if v == -1 or v >= fromBase then
return "数字中包含无效字符或超出原进制范围"
end
decimalFraction = decimalFraction + v * multiplier
multiplier = multiplier / fromBase
end
-- 整数部分:十进制转目标进制
local targetInteger = {}
local n = math.abs(decimalInteger)
if n == 0 then
targetInteger[1] = '0'
else
local i = 0
while n > 0 do
i = i + 1
targetInteger[i] = valueToChar(n % toBase)
n = math.floor(n / toBase)
end
-- 反转数组
for j = 1, math.floor(i / 2) do
targetInteger[j], targetInteger[i - j + 1] = targetInteger[i - j + 1], targetInteger[j]
end
end
-- 小数部分十进制转目标进制精度限制为10位
local targetFraction = {}
local f = decimalFraction
local maxFractionDigits = 10
if f > 0 then
targetFraction[1] = '.'
local i = 1
while f > 0 and i <= maxFractionDigits do
f = f * toBase
local intPart = math.floor(f)
targetFraction[i + 1] = valueToChar(intPart)
f = f - intPart
i = i + 1
end
end
-- 组合结果
local result = {}
if sign == -1 then
result[#result + 1] = '-'
end
for i = 1, #targetInteger do
result[#result + 1] = targetInteger[i]
end
for i = 1, #targetFraction do
result[#result + 1] = targetFraction[i]
end
return table.concat(result)
end
calc_methods["jzzh"] = convertBase
methods_desc["jzzh"] = "数字进制转换支持2~36进制"
-- 执行普通计算的辅助函数
local function execute_normal_calculation(input, seg, express, env)
if (string.len(express) < 2) and (not calc_methods[express]) then return end
if (string.len(express) == 2) and (express:match("^%d[^%!]$")) then return end
local code = replaceToFactorial(express)
local loaded_func, load_error = load("return " .. code, "calculate", "t", calc_methods)
if loaded_func then
local success, result = pcall(loaded_func)
if success then
local display_value
if type(result) == "number" then
display_value = format_number_for_display(result)
else
display_value = tostring(result)
end
yield(Candidate(input, seg.start, seg._end, display_value, ""))
yield(Candidate(input, seg.start, seg._end, express .. "=" .. display_value, ""))
else
yield(Candidate(input, seg.start, seg._end, express, "执行错误"))
end
else
yield(Candidate(input, seg.start, seg._end, express, "解析失败"))
end
end
-- 执行函数调用的辅助函数
local function execute_function_call(input, seg, func_name, params, env)
-- 检查函数是否存在
if not calc_methods[func_name] then
yield(Candidate(input, seg.start, seg._end, "错误: 函数 " .. func_name .. " 不存在", ""))
return
end
local func = calc_methods[func_name]
-- 获取函数的参数数量
local function get_function_param_count(func)
if type(func) ~= "function" then
return nil -- 不是函数返回nil
end
-- 获取函数的字符串表示,从中提取参数信息
local func_str = string.dump(func)
if not func_str then return nil end
-- 从函数的调试信息中获取参数数量(更可靠的方法)
local info = debug.getinfo(func)
if info and info.nparams then
return info.nparams
end
return nil -- 无法确定参数数量
end
-- 获取函数的参数数量
local expected_param_count = get_function_param_count(func)
-- 如果有明确的参数数量要求,进行验证
if expected_param_count and expected_param_count > 0 then
if #params ~= expected_param_count then
yield(Candidate(input, seg.start, seg._end,
"错误: 函数 " .. func_name .. " 需要 " .. expected_param_count .. " 个参数,但提供了 " .. #params .. "", ""))
return
end
end
local function smart_quote_params(param_list, fn_name)
-- 判断哪些函数需要特殊处理其字符串参数
-- key: 函数名, value: 需要加引号的参数索引表
local string_param_funcs = {
jzzh = {1}, -- jzzh函数的第1个参数要转换的数字可能需要引号
dwhs = {2, 3} -- dwhs函数的第2原单位和第3目标单位个参数需要引号
}
local indices_to_quote = string_param_funcs[fn_name]
if not indices_to_quote then
-- 如果这个函数不需要特殊处理,直接返回原参数列表
return param_list
end
local processed_params = {}
for i, param in ipairs(param_list) do
local p = param
-- 检查当前参数索引是否需要被引号包裹
for _, idx in ipairs(indices_to_quote) do
if i == idx then
-- 检查这个参数:如果它不是纯数字,也不是一个已经被引号括起来的字符串,则为其加上引号
if not p:match("^%d+$") and not p:match("^['\"].*['\"]$") then
p = "'" .. p .. "'"
end
break -- 找到匹配的索引后就跳出内层循环
end
end
table.insert(processed_params, p)
end
return processed_params
end
local success, result
-- 关键修改:正确处理无参数情况
if #params > 0 then
-- 有参数的情况:构建函数调用字符串
-- 在处理参数之前,先进行智能引号处理
local processed_params = smart_quote_params(params, func_name)
local param_str = table.concat(processed_params, ", ")
local call_str = func_name .. "(" .. param_str .. ")"
local loaded_func, load_error = load("return " .. call_str, "calculate", "t", calc_methods)
if loaded_func then
success, result = pcall(loaded_func)
else
success = false
result = "函数调用语法错误: " .. tostring(load_error)
end
else
-- 无参数情况:直接调用函数
if type(func) == "function" then
success, result = pcall(func)
else
-- 如果不是函数,可能是其他类型的值
success = true
result = func
end
end
-- 显示结果
if success then
-- 关键修改:正确处理函数返回值
if type(result) == "function" then
-- 如果结果是函数,说明需要执行它
success, result = pcall(result)
if not success then
yield(Candidate(input, seg.start, seg._end, "错误: 函数执行失败: " .. tostring(result), ""))
return
end
end
local display_value
if type(result) == "number" then
display_value = format_number_for_display(result)
else
display_value = tostring(result)
end
-- 显示当前结果
yield(Candidate(input, seg.start, seg._end, display_value, ""))
-- 显示完整调用
local param_display = #params > 0 and table.concat(params, ", ") or ""
local call_display = func_name .. "(" .. param_display .. ")"
yield(Candidate(input, seg.start, seg._end, call_display .. " = " .. display_value, ""))
else
-- 显示错误信息
yield(Candidate(input, seg.start, seg._end, "错误: " .. tostring(result), ""))
end
end
function T.func(input, seg, env)
local composition = env.engine.context.composition
if composition:empty() then return end
local segment = composition:back()
if startsWith(input, T.prefix) or (seg:has_tag("calculator")) then
segment.prompt = "" .. T.tips .. ""
segment.tags = segment.tags + Set({ "calculator" })
-- 提取算式
local express = input:gsub(T.prefix, ""):gsub("^/vs", "")
local code = replaceToFactorial(express)
local loaded_func, load_error = load("return " .. code, "calculate", "t", calc_methods)
if loaded_func and (type(methods_desc[code]) == "string") then
yield(Candidate(input, seg.start, seg._end, express .. ":" .. methods_desc[code], ""))
end
-- 检查是否是单个全局变量(不包含运算符的纯标识符)
if express:match("^[a-zA-Z][a-zA-Z0-9_]*$") then
local identifier = express
local value = calc_methods[identifier]
-- 如果是已定义的数值常量,直接显示其值
if type(value) == "number" then
local formatted_result = format_number_for_display(value)
local description = methods_desc[identifier] or ""
-- 创建候选词
local cand = Candidate("calculator", seg.start, seg._end, formatted_result, description)
cand.preedit = input
cand.quality = 100
yield(cand)
-- 同时显示带变量名的完整表达式结果
local expr_cand = Candidate("calculator", seg.start, seg._end,
identifier .. " = " .. formatted_result, description)
expr_cand.preedit = input
expr_cand.quality = 99
yield(expr_cand)
return
end
-- 让全局变量可以参与运算
elseif express:match("^([a-zA-Z][a-zA-Z0-9_]*)") then
local identifier = express:match("^([a-zA-Z][a-zA-Z0-9_]*)")
if identifier then
local value = calc_methods[identifier]
-- 如果是已定义的数值常量,按普通计算处理
if type(value) == "number" then
execute_normal_calculation(input, seg, express, env)
return
end
end
end
-- 检查是否是函数调用(英文字母开头且不包含括号)
if express:match("^[a-zA-Z]") and not express:find("[()]") then
-- 尝试按免括号方式处理函数调用
local func_name = nil
local param_part = ""
-- 从长到短尝试匹配函数名
for i = #express, 1, -1 do
local potential_name = express:sub(1, i)
if calc_methods[potential_name] ~= nil then
func_name = potential_name
param_part = express:sub(i + 1)
break
end
end
if func_name then
-- 如果找到函数名,提取参数部分
local params = {}
if param_part and param_part ~= "" then
local current_param = ""
local in_quotes = false
local quote_char = ""
for i = 1, #param_part do
local char = param_part:sub(i, i)
if in_quotes then
if char == quote_char then
in_quotes = false
table.insert(params, current_param)
current_param = ""
else
current_param = current_param .. char
end
else
if char == '"' or char == "'" then
in_quotes = true
quote_char = char
if current_param ~= "" then
table.insert(params, current_param)
current_param = ""
end
elseif char == "," then
if current_param ~= "" then
table.insert(params, current_param)
current_param = ""
end
else
current_param = current_param .. char
end
end
end
if current_param ~= "" then
table.insert(params, current_param)
end
end
-- 清理参数
for i, param in ipairs(params) do
params[i] = param:match("^%s*(.-)%s*$")
end
-- 执行函数
execute_function_call(input, seg, func_name, params, env)
return
end
end
-- 其他情况执行普通计算
execute_normal_calculation(input, seg, express, env)
end
end
return T