- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图获得一个在运行时只初始化一次的变量。
在 C/C++ 中 static
将是我要寻找的关键字,但在 Rust 中,它必须由常量初始化。static mut
是不安全的,我可以理解为什么,但它在概念上没有捕捉到我想要的东西,我想要一个不可变的变量。
以这个 tribonacci 函数的简单示例为例:
static sqrt_33_mul_3: f64 = 3.0 * 33.0f64.powf(0.5);
static tribonacci_constant: f64 = 1.0
+ (19.0 - sqrt_33_mul_3).powf(1.0 / 3.0)
+ (19.0 + sqrt_33_mul_3).powf(1.0 / 3.0);
fn tribonacci(n: f64) -> f64 {
return (
(tribonacci_constant / 3.0).powf(n)
/ (
(4.0 / 3.0)
* tribonacci_constant
- (1.0 / 9.0)
* tribonacci_constant.powf(2.0) - 1.0
)
).round();
}
我希望函数外部的两个静态变量只初始化一次,并且每次运行函数时都不调用 powf
最佳答案
如 f64::powf
是一个 const 函数,那么编译器应该转换类似 3.0 * 33.0f64.powf(0.5)
的东西降低到一个固定值。
虽然 lazy_static
可以用来解决这个问题,使用lazy_statics 是有代价的,因为它们的设计目的不仅仅是支持简单的浮点常量。
您可以通过使用 Criterion 对两个实现进行基准测试来查看此成本:
pub mod ls {
use lazy_static::lazy_static; // 1.4.0
lazy_static! {
//TODO: Should this be a pow(1.0/3.0)?
pub static ref cbrt_33_mul_3: f64 = 3.0 * 33.0f64.powf(0.5);
pub static ref tribonacci_constant: f64 = 1.0
+ (19.0 - *cbrt_33_mul_3).powf(1.0 / 3.0)
+ (19.0 + *cbrt_33_mul_3).powf(1.0 / 3.0);
}
pub fn tribonacci(n: f64) -> f64 {
return (
(*tribonacci_constant / 3.0).powf(n)
/ (
(4.0 / 3.0)
* *tribonacci_constant
- (1.0 / 9.0)
* tribonacci_constant.powf(2.0) - 1.0
)
).round();
}
}
pub mod hc {
pub fn tribonacci(n: f64) -> f64 {
let p = 1.839286755214161;
let s = 0.3362281169949411;
return (s * p.powf(n)).round();
}
}
fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("trib 5.1 ls", |b| b.iter(|| ls::tribonacci(black_box(5.1))));
c.bench_function("trib 5.1 hc", |b| b.iter(|| hc::tribonacci(black_box(5.1))));
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
成本很小,但如果这是在您的核心循环中,则可能会很大。
trib 5.1 ls time: [47.946 ns 48.832 ns 49.796 ns]
trib 5.1 hc time: [38.828 ns 39.898 ns 41.266 ns]
这大约有 20% 的差异。
build.rs
生成这些常量。脚本。
use std::env;
use std::fs;
use std::path::Path;
fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("constants.rs");
//TODO: Should this be a pow(1.0/3.0)?
let cbrt_33_mul_3: f64 = 3.0 * 33.0f64.powf(0.5);
let tribonacci_constant: f64 = 1.0
+ (19.0 - cbrt_33_mul_3).powf(1.0 / 3.0)
+ (19.0 + cbrt_33_mul_3).powf(1.0 / 3.0);
let p = tribonacci_constant / 3.0;
let s = 1.0 / (
(4.0 / 3.0)
* tribonacci_constant
- (1.0 / 9.0)
* tribonacci_constant.powf(2.0) - 1.0
);
fs::write(
&dest_path,
format!("\
pub mod tribonacci {{\n\
pub const P: f64 = {:.32};\n\
pub const S: f64 = {:.32};\n\
}}\n", p, s)
).unwrap();
println!("cargo:rerun-if-changed=build.rs");
}
src/lib.rs
pub mod constants {
include!(concat!(env!("OUT_DIR"), "/constants.rs"));
}
pub mod ls {
use lazy_static::lazy_static; // 1.4.0
lazy_static! {
//TODO: Should this be a pow(1.0/3.0)?
pub static ref cbrt_33_mul_3: f64 = 3.0 * 33.0f64.powf(0.5);
pub static ref tribonacci_constant: f64 = 1.0
+ (19.0 - *cbrt_33_mul_3).powf(1.0 / 3.0)
+ (19.0 + *cbrt_33_mul_3).powf(1.0 / 3.0);
}
pub fn tribonacci(n: f64) -> f64 {
return (
(*tribonacci_constant / 3.0).powf(n)
/ (
(4.0 / 3.0)
* *tribonacci_constant
- (1.0 / 9.0)
* tribonacci_constant.powf(2.0) - 1.0
)
).round();
}
}
pub mod hc {
pub fn tribonacci(n: f64) -> f64 {
let p = super::constants::tribonacci::P;
let s = super::constants::tribonacci::S;
return (s * p.powf(n)).round();
}
}
长凳/my_benchmark.rs
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use rust_gen_const_vs_lazy_static::ls;
use rust_gen_const_vs_lazy_static::hc;
fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("trib 5.1 ls", |b| b.iter(|| ls::tribonacci(black_box(5.1))));
c.bench_function("trib 5.1 hc", |b| b.iter(|| hc::tribonacci(black_box(5.1))));
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
Cargo.toml
[package]
name = "rust_gen_const_vs_lazy_static"
version = "0.1.0"
edition = "2018"
[dependencies]
"lazy_static" = "1.4.0"
[dev-dependencies]
criterion = "0.3"
[[bench]]
name = "my_benchmark"
harness = false
$OUTDIR/constants.rs (生成)
pub mod tribonacci {
pub const P: f64 = 1.83928675521416096216853475198150;
pub const S: f64 = 0.33622811699494109527464047459944;
}
trib_macros
,因为 proc-macros 需要在他们自己的箱子里。这个新箱子只包含两个文件
Cargo.toml
和
src/lib.rs
Cargo.toml
[package]
name = "trib_macros"
version = "0.1.0"
edition = "2018"
[lib]
proc-macro = true
src/lib.rs
extern crate proc_macro;
use proc_macro::TokenStream;
#[proc_macro]
pub fn tp(_item: TokenStream) -> TokenStream {
let cbrt_33_mul_3: f64 = 3.0 * 33.0f64.powf(0.5);
let tribonacci_constant: f64 = 1.0
+ (19.0 - cbrt_33_mul_3).powf(1.0 / 3.0)
+ (19.0 + cbrt_33_mul_3).powf(1.0 / 3.0);
let p = tribonacci_constant / 3.0;
format!("{}f64",p).parse().unwrap()
}
#[proc_macro]
pub fn ts(_item: TokenStream) -> TokenStream {
let cbrt_33_mul_3: f64 = 3.0 * 33.0f64.powf(0.5);
let tribonacci_constant: f64 = 1.0
+ (19.0 - cbrt_33_mul_3).powf(1.0 / 3.0)
+ (19.0 + cbrt_33_mul_3).powf(1.0 / 3.0);
let s = 1.0 / (
(4.0 / 3.0)
* tribonacci_constant
- (1.0 / 9.0)
* tribonacci_constant.powf(2.0) - 1.0
);
format!("{}f64",s).parse().unwrap()
}
然后我们需要调整
Cargo.toml
把它拉进来的原始 crate 。
[dependencies]
...
trib_macros = { path = "path/to/trib_macros" }
最后使用起来还是比较干净的:
pub mod mc {
use trib_macros::{ts,tp};
pub fn tribonacci(n: f64) -> f64 {
return (ts!() * tp!().powf(n)).round();
}
}
肯定有一种更简洁的方法来输出浮点文字标记,但我找不到它。
关于rust - 如何在 Rust 中使用非常量初始化程序初始化不可变的全局变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65120456/
我需要将文本放在 中在一个 Div 中,在另一个 Div 中,在另一个 Div 中。所以这是它的样子: #document Change PIN
奇怪的事情发生了。 我有一个基本的 html 代码。 html,头部, body 。(因为我收到了一些反对票,这里是完整的代码) 这是我的CSS: html { backgroun
我正在尝试将 Assets 中的一组图像加载到 UICollectionview 中存在的 ImageView 中,但每当我运行应用程序时它都会显示错误。而且也没有显示图像。 我在ViewDidLoa
我需要根据带参数的 perl 脚本的输出更改一些环境变量。在 tcsh 中,我可以使用别名命令来评估 perl 脚本的输出。 tcsh: alias setsdk 'eval `/localhome/
我使用 Windows 身份验证创建了一个新的 Blazor(服务器端)应用程序,并使用 IIS Express 运行它。它将显示一条消息“Hello Domain\User!”来自右上方的以下 Ra
这是我的方法 void login(Event event);我想知道 Kotlin 中应该如何 最佳答案 在 Kotlin 中通配符运算符是 * 。它指示编译器它是未知的,但一旦知道,就不会有其他类
看下面的代码 for story in book if story.title.length < 140 - var story
我正在尝试用 C 语言学习字符串处理。我写了一个程序,它存储了一些音乐轨道,并帮助用户检查他/她想到的歌曲是否存在于存储的轨道中。这是通过要求用户输入一串字符来完成的。然后程序使用 strstr()
我正在学习 sscanf 并遇到如下格式字符串: sscanf("%[^:]:%[^*=]%*[*=]%n",a,b,&c); 我理解 %[^:] 部分意味着扫描直到遇到 ':' 并将其分配给 a。:
def char_check(x,y): if (str(x) in y or x.find(y) > -1) or (str(y) in x or y.find(x) > -1):
我有一种情况,我想将文本文件中的现有行包含到一个新 block 中。 line 1 line 2 line in block line 3 line 4 应该变成 line 1 line 2 line
我有一个新项目,我正在尝试设置 Django 调试工具栏。首先,我尝试了快速设置,它只涉及将 'debug_toolbar' 添加到我的已安装应用程序列表中。有了这个,当我转到我的根 URL 时,调试
在 Matlab 中,如果我有一个函数 f,例如签名是 f(a,b,c),我可以创建一个只有一个变量 b 的函数,它将使用固定的 a=a1 和 c=c1 调用 f: g = @(b) f(a1, b,
我不明白为什么 ForEach 中的元素之间有多余的垂直间距在 VStack 里面在 ScrollView 里面使用 GeometryReader 时渲染自定义水平分隔线。 Scrol
我想知道,是否有关于何时使用 session 和 cookie 的指南或最佳实践? 什么应该和什么不应该存储在其中?谢谢! 最佳答案 这些文档很好地了解了 session cookie 的安全问题以及
我在 scipy/numpy 中有一个 Nx3 矩阵,我想用它制作一个 3 维条形图,其中 X 轴和 Y 轴由矩阵的第一列和第二列的值、高度确定每个条形的 是矩阵中的第三列,条形的数量由 N 确定。
假设我用两种不同的方式初始化信号量 sem_init(&randomsem,0,1) sem_init(&randomsem,0,0) 现在, sem_wait(&randomsem) 在这两种情况下
我怀疑该值如何存储在“WORD”中,因为 PStr 包含实际输出。? 既然Pstr中存储的是小写到大写的字母,那么在printf中如何将其给出为“WORD”。有人可以吗?解释一下? #include
我有一个 3x3 数组: var my_array = [[0,1,2], [3,4,5], [6,7,8]]; 并想获得它的第一个 2
我意识到您可以使用如下方式轻松检查焦点: var hasFocus = true; $(window).blur(function(){ hasFocus = false; }); $(win
我是一名优秀的程序员,十分优秀!