Lua 浮点数比较

更简单
lua 复制代码
-- 默认容差为 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()  -- 取消注释以运行测试
相关推荐
yuyuyuliang002 小时前
python笔记1
开发语言·笔记·python
摇滚侠2 小时前
Groovy 如何给集合中添加元素
java·开发语言·windows·python
~plus~2 小时前
C# 事件溯源与 CQRS 架构:用 EventStoreDB 打造可靠系统
开发语言·架构·c#
江奖蒋犟2 小时前
【C++】红黑树
开发语言·c++
雒珣2 小时前
Qt实现命令行参数功能示例:QCommandLineParser
开发语言·数据库·qt
无巧不成书02182 小时前
Java异常体系与处理全解:核心原理、实战用法、避坑指南
java·开发语言·异常处理·java异常处理体系
大尚来也3 小时前
Go性能调优实战:用pprof精准定位瓶颈
开发语言
User_芊芊君子3 小时前
2026 Python+AI入门|0基础速通,吃透热门轻量化玩法
开发语言·人工智能·python
aq55356003 小时前
Laravel7.x重磅升级:十大新特性解析
开发语言·汇编·c#·html