简介
Rust基础
基础类型
整数类型
浮点类型
浮点类型特殊存储格式导致的 0.1+0.2 != 0.3 的问题( 存储格式导致精度的问题)
fn get_var_type<T>( _ : &T ) -> &str {
std::any::type_name::<T>()
}
fn main() {
let abc: (f32, f32, f32) = (0.1, 0.2, 0.3);
let xyz: (f64, f64, f64) = (0.1, 0.2, 0.3);
println!("abc【{}】 {:?}",get_var_type(&abc),abc); // {:?} 打印详细集合元素
println!("abc.0={} 十进制打印 bit={} ",abc.0,abc.0.to_bits());
println!("abc.0={} 十六进制打印 bit={:x} ",abc.0,abc.0.to_bits()); // {:x} 打印 16进制 输出显示
println!("abc.0={} bit={:x}",abc.0,abc.0.to_bits());
println!("abc.1={} bit={:x}",abc.1,abc.1.to_bits());
println!("abc.2={} bit={:x}",abc.2,abc.2.to_bits());
// println!("abc.3={} bit={}",abc.3,abc.3.to_bits()); // 编译不过 这样就避免了其他语言的运行时错误 no field `3` on type `(f32, f32, f32)`
println!(" 0.1 + 0.2: {:x}", (abc.0 + abc.1).to_bits());
println!(" 0.3: {:x}", (abc.2).to_bits());
println!();
println!("xyz【{}】 {:?}",get_var_type(&xyz),xyz);
println!("xyz.0={} 十进制打印 bit={}",xyz.0,xyz.0.to_bits());
println!("xyz.0={} 十六进制打印 bit={:x}",xyz.0,xyz.0.to_bits()); // {:x} 打印 16进制 输出显示
println!("xyz.0={} bit={:x}",xyz.0,xyz.0.to_bits());
println!("xyz.1={} bit={:x}",xyz.1,xyz.1.to_bits());
println!("xyz.2={} bit={:x}",xyz.2,xyz.2.to_bits());
println!(" 0.1 + 0.2: {:x} 【这里是4结尾】", (xyz.0 + xyz.1).to_bits()); // {:x} 打印 16进制 输出显示
println!(" 0.3: {:x} 【这里是3结尾】", (xyz.2).to_bits());
println!();
let f32_bool_flag = (abc.0 + abc.1 == abc.2);
println!("abc.0 + abc.1 == abc.2 ----> f32_bool_flag【{}】 tip:精度低导致f32相加字节层面相同(浮点数字节存储格式导致)",f32_bool_flag);
let f64_bool_flag = (xyz.0 + xyz.1 == xyz.2);
println!("xyz.0 + xyz.1 == xyz.2 ----> f64_bool_flag【{}】 tip:精度低导致f64相加字节层面不相同(浮点数字节存储格式导致)",f64_bool_flag);
println!();
println!("int 打印 二进制格式");
let ijk: (i32, i32, i32) = (30, 60, 90);
// println!("ijk.0={} bit={:x}",ijk.0,ijk.0.to_bits()); // 报错: i32 没有对应的 to_bits() 方法 只有浮点类型有这个方法
println!("ijk【{}】 {:?}",get_var_type(&ijk),ijk); // {:?} 打印详细集合元素
println!("ijk.0={} 二进制打印 bit= {:b} ",ijk.0,ijk.0); // {:b} 打印 2进制 输出显示 显示
println!("ijk.0={} 八进制打印 ijk.0={:o} ",ijk.0,ijk.0); // {:o} 打印 8进制 输出显示
println!("ijk.0={} 十进制打印 ijk.0={} ",ijk.0,ijk.0); // {} 十进制打印
println!("ijk.0={} 十六进制打印 ijk.0=={:x} ",ijk.0,ijk.0); // {:x} 打印 16进制 输出
println!("ijk.0={} bit={:b}",ijk.0,ijk.0);
println!("ijk.1={} bit={:b}",ijk.1,ijk.1);
println!("ijk.2={} bit={:b}",ijk.2,ijk.2);
println!(" 0.1 + 0.2: {:x}", (ijk.0 + ijk.1));
println!(" 0.3: {:x}", (ijk.2));
println!();
}
/*输出结果:
abc【(f32, f32, f32)】 (0.1, 0.2, 0.3)
abc.0=0.1 十进制打印 bit=1036831949
abc.0=0.1 十六进制打印 bit=3dcccccd
abc.0=0.1 bit=3dcccccd
abc.1=0.2 bit=3e4ccccd
abc.2=0.3 bit=3e99999a
0.1 + 0.2: 3e99999a
0.3: 3e99999a
xyz【(f64, f64, f64)】 (0.1, 0.2, 0.3)
xyz.0=0.1 十进制打印 bit=4591870180066957722
xyz.0=0.1 十六进制打印 bit=3fb999999999999a
xyz.0=0.1 bit=3fb999999999999a
xyz.1=0.2 bit=3fc999999999999a
xyz.2=0.3 bit=3fd3333333333333
0.1 + 0.2: 3fd3333333333334 【这里是4结尾】
0.3: 3fd3333333333333 【这里是3结尾】
abc.0 + abc.1 == abc.2 ----> f32_bool_flag【true】 tip:精度低导致f32相加字节层面相同(浮点数字节存储格式导致)
xyz.0 + xyz.1 == xyz.2 ----> f64_bool_flag【false】 tip:精度低导致f64相加字节层面不相同(浮点数字节存储格式导致)
int 打印 二进制格式
ijk【(i32, i32, i32)】 (30, 60, 90)
ijk.0=30 二进制打印 bit= 11110
ijk.0=30 八进制打印 ijk.0=36
ijk.0=30 十进制打印 ijk.0=30
ijk.0=30 十六进制打印 ijk.0==1e
ijk.0=30 bit=11110
ijk.1=60 bit=111100
ijk.2=90 bit=1011010
0.1 + 0.2: 5a
0.3: 5a
仔细看,对 f32 类型做加法时,0.1 + 0.2 的结果是 3e99999a,0.3 也是 3e99999a,
因此 f32 下的 0.1 + 0.2 == 0.3 通过测试,但是到了 f64 类型时,结果就不一样了,
因为 f64 精度高很多,因此在小数点非常后面发生了一点微小的变化,0.1 + 0.2 以 4 结尾,
但是 0.3 以3结尾,这个细微区别导致 f64 下的测试失败了,并且抛出了异常。
*/
NaN类型
fn get_var_type<T>( _ : &T ) -> &str {
std::any::type_name::<T>()
}
fn main() {
let x = (-42.0_f64).sqrt(); // f32 f64 浮点类型 才有的方法 sqrt()
let y = (42.0_f64).sqrt();
// let z = (-42_i32).sqrt(); // i32 i64 整数类型 没有求 sqrt() 平方根的方法 报错 method sqrt not found in `i32`
println!("x_type[{}] x={}",get_var_type(&x), x);
println!("y_type[{}] y={}",get_var_type(&y), y);
// i32 i64 整数类型 判断 is_nan() 非意义的方法 报错 method is_nan not found in `i32`
// let a_int: i32 = 10;
// if a_int.is_nan() { println!("a_int 是 nan 意味着 未定义的数学行为") }
if x.is_nan() {
println!("x 是 float 浮点类型的 nan 意味着 未定义的数学行为")
}
}
/*
x_type[f64] x=NaN
y_type[f64] y=6.48074069840786
x 是 float 浮点类型的 nan 意味着 未定义的数学行为
*/