You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为f64类型构建ln值查找表的最优实现方案

方案推荐

1. 标准库无依赖实现(Rust 1.70+ 优先选择)

不用引入任何第三方 crate,直接用标准库的OnceLock加互斥锁实现线程安全的全局可扩容查找表:

use std::sync::{OnceLock, Mutex};

// 全局静态查找表,仅初始化一次
static LNS_LOOKUP: OnceLock<Mutex<Vec<f64>>> = OnceLock::new();

pub fn get_ln(i: u32) -> f64 {
    // 首次调用时初始化基础表,前两个元素为0.0
    let lookup = LNS_LOOKUP.get_or_init(|| {
        Mutex::new(vec![0.0f64, 0.0f64])
    });
    let mut table = lookup.lock().unwrap();
    let i_usize = i as usize;

    // 当请求的下标超过当前表长时自动追加计算
    if i_usize >= table.len() {
        for n in table.len()..=i_usize {
            table.push((n as f64).ln());
        }
    }

    table[i_usize]
}

该实现的优势:

  • 无需手动预填常量,所有对数值自动计算
  • 仅首次调用初始化基础表,后续相同值直接查表,无重复计算
  • 支持动态扩容,遇到更大的i时自动追加新的对数值
  • 线程安全,多线程场景下可直接使用

2. 单线程场景优化版

如果你的代码仅在单线程下运行,可以去掉锁开销,用线程本地存储实现,性能更高:

use std::cell::RefCell;

thread_local! {
    static LNS_LOOKUP: RefCell<Vec<f64>> = RefCell::new(vec![0.0f64, 0.0f64]);
}

pub fn get_ln(i: u32) -> f64 {
    LNS_LOOKUP.with(|lookup| {
        let mut table = lookup.borrow_mut();
        let i_usize = i as usize;
        if i_usize >= table.len() {
            for n in table.len()..=i_usize {
                table.push((n as f64).ln());
            }
        }
        table[i_usize]
    })
}

3. 旧版本Rust兼容方案(需lazy_static依赖)

如果你的Rust版本低于1.70,无法使用标准库的OnceLock,可以用lazy_static crate实现,代码逻辑和标准库版本基本一致:

use lazy_static::lazy_static;
use std::sync::Mutex;

lazy_static! {
    static ref LNS_LOOKUP: Mutex<Vec<f64>> = Mutex::new(vec![0.0f64, 0.0f64]);
}

pub fn get_ln(i: u32) -> f64 {
    let mut table = LNS_LOOKUP.lock().unwrap();
    let i_usize = i as usize;
    if i_usize >= table.len() {
        for n in table.len()..=i_usize {
            table.push((n as f64).ln());
        }
    }
    table[i_usize]
}

内容的提问来源于stack exchange,提问作者C. Bartels

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 17:18:03