-- 默认容差为 1e-12(可根据实际精度调整)
function float_eq(a, b, epsilon)
epsilon = epsilon or 1e-12
return math.abs(a - b) <= epsilon
end
-- 容差比较基础函数
function nearly_equal(a, b, eps)
eps = eps or 1e-12
return math.abs(a - b) <= eps
end
-- a < b
function float_lt(a, b, eps)
return a + (eps or 1e-12) < b
end
-- a <= b
function float_le(a, b, eps)
return a <= b + (eps or 1e-12)
end
-- a > b
function float_gt(a, b, eps)
return a > b + (eps or 1e-12)
end
-- a >= b
function float_ge(a, b, eps)
return a + (eps or 1e-12) >= b
end
更安全
lua复制代码
-- ============================================================================
-- 浮点数比较
-- ============================================================================
local math_abs = math.abs
local math_max = math.max
-- 默认绝对容差(适用于接近零的值)
local DEFAULT_EPS_ABS = 1e-12
-- 默认相对容差(适用于大数值)
local DEFAULT_EPS_REL = 1e-12
-- 判断一个数是否为 NaN(Lua 中直接比较 x ~= x 即可)
local function is_nan(x)
return x ~= x
end
-- 判断一个数是否为有限数(非 NaN 且非无穷)
local function is_finite(x)
if x ~= x then return false end -- NaN
if x == math.huge or x == -math.huge then return false end
return true
end
-- ============================================================================
-- 两个浮点数是否近似相等(考虑绝对误差和相对误差)
-- @param a 第一个数
-- @param b 第二个数
-- @param eps_abs 绝对容差(默认 1e-12)
-- @param eps_rel 相对容差(默认 1e-12)
-- @return boolean true 表示相等(在容差范围内)
-- ============================================================================
function float_eq(a, b, eps_abs, eps_rel)
eps_abs = eps_abs or DEFAULT_EPS_ABS
eps_rel = eps_rel or DEFAULT_EPS_REL
-- 处理 NaN:NaN 与任何值(包括自身)都不相等
if is_nan(a) or is_nan(b) then
return false
end
-- 处理无穷大:符号相同的无穷大视为相等
if a == math.huge and b == math.huge then return true end
if a == -math.huge and b == -math.huge then return true end
-- 对于非常大的数,使用相对误差;对于接近零的数,使用绝对误差
local diff = math_abs(a - b)
if diff <= eps_abs then
return true
end
-- 相对误差(防止除以零,取分母绝对值较大者)
local max_val = math_max(math_abs(a), math_abs(b))
if max_val > 0 then
local rel_err = diff / max_val
if rel_err <= eps_rel then
return true
end
end
return false
end
-- ============================================================================
-- 比较 a < b (严格小于,考虑容差)
-- 规则:当 a 明显小于 b 时(差值超过容差)返回 true
-- ============================================================================
function float_lt(a, b, eps_abs, eps_rel)
eps_abs = eps_abs or DEFAULT_EPS_ABS
eps_rel = eps_rel or DEFAULT_EPS_REL
-- NaN 无法比较,返回 false
if is_nan(a) or is_nan(b) then
return false
end
-- 无穷处理:任何有限数 < +inf;-inf < 任何有限数
if a == -math.huge and b ~= -math.huge then return true end
if b == math.huge and a ~= math.huge then return true end
if a == math.huge or b == -math.huge then return false end
-- 如果 a 和 b 近似相等,则不认为 a < b
if float_eq(a, b, eps_abs, eps_rel) then
return false
end
-- 否则直接比较数值
return a < b
end
-- ============================================================================
-- 比较 a <= b (小于等于,考虑容差)
-- ============================================================================
function float_le(a, b, eps_abs, eps_rel)
return float_lt(a, b, eps_abs, eps_rel) or float_eq(a, b, eps_abs, eps_rel)
end
-- ============================================================================
-- 比较 a > b (严格大于)
-- ============================================================================
function float_gt(a, b, eps_abs, eps_rel)
return float_lt(b, a, eps_abs, eps_rel)
end
-- ============================================================================
-- 比较 a >= b
-- ============================================================================
function float_ge(a, b, eps_abs, eps_rel)
return float_gt(a, b, eps_abs, eps_rel) or float_eq(a, b, eps_abs, eps_rel)
end
-- ============================================================================
-- 工具:判断一个数是否为有效的非零浮点数(结合之前的转换函数)
-- 假设 to_float 已经定义(返回 ok, value)
-- ============================================================================
function is_valid_nonzero_float(input)
local ok, val = to_float(input) -- 请确保 to_float 已实现
return ok
end
-- ============================================================================
-- 测试示例(包含边界情况)
-- ============================================================================
local function run_tests()
print("========== 浮点数比较测试 ==========")
-- 基本相等(含精度误差)
print(float_eq(0.1 + 0.2, 0.3)) --> true
print(float_eq(1e-100, 0, 1e-99)) --> true (绝对容差)
print(float_eq(1e100, 1e100 + 1e85, nil, 1e-12)) --> true (相对容差)
-- 不等
print(float_eq(0.1, 0.2)) --> false
-- 无穷大比较
print(float_eq(math.huge, math.huge)) --> true
print(float_eq(math.huge, -math.huge)) --> false
print(float_lt(1e200, math.huge)) --> true
print(float_lt(-math.huge, -1e200)) --> true
-- NaN 比较
local nan = 0/0 -- 在 Lua 中需要某些环境,通常直接构造:tonumber("nan") 或 0*math.huge
-- 由于 Lua 默认不支持 NaN 字面量,用以下方式模拟(如果有)
if is_nan(0/0) then
print(float_eq(nan, nan)) --> false
print(float_lt(nan, 1)) --> false
end
-- 大小比较
print(float_lt(0.1, 0.2)) --> true
print(float_lt(0.2, 0.1)) --> false
print(float_le(0.1, 0.1 + 1e-15)) --> true(容差内视为相等)
print(float_gt(0.2, 0.1)) --> true
print(float_ge(0.1, 0.1 - 1e-15)) --> true
end
-- run_tests() -- 取消注释以运行测试