Rust 整数和浮点数支持的 API
楔子
前面介绍了 Rust 的类型,比如整数、浮点数、数组等等,但我们仅仅是知道这些数据结构,而它们所拥有的方法我们还不是很清楚。在工作中光有数据结构也不够,如果不知道它提供的一系列方法,我们就无法对数据做处理。所以接下来的几篇文章,我们就来看这些数据结构都有哪些方法。
首先从整数和浮点数开始。
整数所拥有的方法
整数是非常简单的数据结构,但它拥有的方法也不少。
MIN:获取指定整数类型的最小值
MAX:获取指定整数类型的最大值
fn main() {
println!("{} {}", i8::MIN, i8::MAX);
println!("{} {}", u16::MIN, u16::MAX);
println!("{} {}", i32::MIN, i32::MAX);
/*
-128 127
0 65535
-2147483648 2147483647
*/
}
BITS:获取指定整数类型的位数
fn main() {
println!("{} {}", i8::BITS, u32::BITS); // 8 32
}
from_str_radix:将字符串切片转成整数
fn main() {
// i16::from_str_radix 返回 Result<i16, ParseIntError>
// 第一个参数是字符串切片,第二个参数是进制
println!("{:?}", i16::from_str_radix("123", 10)); // Ok(123)
println!("{:?}", u32::from_str_radix("123", 10)); // Ok(123)
println!("{:?}", u32::from_str_radix("111", 2)); // Ok(7)
println!("{:?}", u32::from_str_radix("FFFF", 16)); // Ok(65535)
println!("{:?}", u32::from_str_radix("abc", 16)); // Ok(2748)
println!("{:?}", i64::from_str_radix("abc", 10)); // Err(ParseIntError { kind: InvalidDigit })
}
当然,里面包含正负号也是可以解析的。
fn main() {
println!("{:?}", i16::from_str_radix("+123", 10)); // Ok(123)
println!("{:?}", i32::from_str_radix("-123", 10)); // Ok(-123)
// u32 无法解析负数
println!("{:?}", u32::from_str_radix("-123", 10)); // Err(ParseIntError { kind: InvalidDigit })
}
to_string:将整数转成字符串(String)
fn main() {
println!("{}", 123.to_string()); // 123
}
count_ones:返回整数对应的二进制中有多少个 1
count_zeros:返回整数对应的二进制中有多少个 0
fn main() {
let n: i32 = 0b101101001;
println!("{:?}", n.count_ones()); // 5
// n 是 32 位整数,1 有 5 个,所以 0 有 27 个
println!("{:?}", n.count_zeros()); // 27
}
leading_zeros:返回整数对应的二进制中前导 0 的个数
fn main() {
let n: i32 = 0b101101001;
println!("{:?}", n.count_zeros()); // 27
// 从最高位往右数,直到遇见第一个不是 0
println!("{:?}", n.leading_zeros()); // 23
// 从最低位往左数,直到遇见第一个不是 0
println!("{:?}", n.trailing_zeros()); // 0
// 从最高位往右数,直到遇见第一个不是 1
println!("{:?}", n.leading_ones()); // 0
// 从最低位往左数,直到遇见第一个不是 1
println!("{:?}", n.trailing_ones()); // 1
}
rotate_left:左移 n 个位,将截断的 n 个位拼接到整数的末尾
fn main() {
let n: u8 = 0b1011_1111;
// 左移 2 两位(显然高位的 10 会被阶段),将其拼接到末尾,所以结果是 0b1111_1110
println!("{} {}", n.rotate_left(2), 0b1111_1110); // 254 254
// 注意:这和左移不同,如果是左移,那么会在低位补 0
// rotate_left 是将截断的位拼接在整数的尾部
print!("{} {}", n << 2, 0b1111_1100); // 252 252
}
同理还有 rotate_right,右移 n 个位,并将截断的 n 个位拼接到整数的开头。
reverse_bits:将整数的位进行反转,低位变高位,高位变低位
fn main() {
let n: u8 = 0b1111_0000;
println!("{} {}", n.reverse_bits(), 0b0000_1111); // 254 254
}
overflowing_add:加法运算,当溢出时进行环绕
fn main() {
let n: u8 = 255;
// n + 10 会出现溢出,所以采用 overflowing_add,当溢出时进行环绕
// 如果 n + 10 > u8::MAX,那么结果为 (n + 10) - 2 ^ 8
let (result, ok) = n.overflowing_add(10);
// 如果溢出,ok 为 true,否则为 false
println!("{} {}", result, (n as u16 + 10) - 256); // 9 9
}
同理还有overflowing_sub、overflowing_mul、overflowing_div。
ilog:计算对数
fn main() {
let n: u8 = 255;
println!("{}", n.ilog(15)); // 2
// 如果底数为 2,那么可以使用 ilog2,底数为 10,可以使用 ilog10
println!("{} {}", 16u8.ilog2(), 1000u32.ilog10()); // 4 3
}
abs:获取整数的绝对值
fn main() {
let n: i32 = -255;
println!("{}", n.abs()); // 255
}
pow:获取整数的 n 次幂
fn main() {
println!("{}", 2i32.pow(4)); // 16
}
以上就是整数所拥有的一系列方法,当然还有很多其它方法,不过不常用,有兴趣可以查看官网。
浮点数所拥有的方法
看完了整数,再来看看浮点数。需要先说明的是,有很多的我们常见的方法,比如求对数、求平方根等等,这些方法整数是没有的,但浮点数有。所以如果整数想使用这些方法,需要先转成浮点数。
整数和浮点数的相互转化
fn main() {
println!("{} {}", 3.14 as i32, 123 as f64); // 3 123
println!("{} {}", -3.14 as i32, -123 as f64); // -3 -123
}
floor:向下取整,返回浮点数
fn main() {
println!("{} {}", 4.2f32.floor(), (-4.2f32).floor()) // 4 -5
}
ceil:向上取整,返回浮点数
fn main() {
println!("{} {}", 4.2f32.ceil(), (-4.2f32).ceil()) // 5 -4
}
round:四舍五入,返回浮点数
fn main() {
// 这里补充一点,由于 f32 和 f64 的方法是相同的
// 所以通过字面量来调用的话,Rust 不知道字面量的类型,所以需要显式指定
println!("{}", 3.3333f64.round()); // 3
println!("{}", 3.5333f64.round()); // 4
}
trunc:截断,返回浮点数,注意它和 floor 的差别
fn main() {
let f = 3.7_f32;
let g = 3.0_f32;
let h = -3.7_f32;
println!("{} {}", f.trunc(), f.floor()); // 3 3
println!("{} {}", g.trunc(), g.floor()); // 3 3
println!("{} {}", h.trunc(), h.floor()); // -3 -4
// trunc 和 as 的作用比较类似
println!("{} {}", f as i32, h as i32); // 3 -3
}
fract:返回浮点数的小数部分
fn main() {
let x = 3.6_f32;
let y = -3.6_f32;
println!("{} {}", x.fract(), y.fract()) // 0.5999999 -0.5999999
}
abs:返回浮点数的绝对值
fn main() {
let x = 3.6_f32;
let y = -3.6_f32;
println!("{} {}", x.abs(), y.abs()) // 3.6 3.6
}
signum:返回浮点数的符号(浮点数),大于等于 0 返回 1,负数返回 -1
fn main() {
let x = 3.6_f32;
let y = -3.6_f32;
println!("{} {} {}", x.signum(), y.signum(), 0.0f32.signum()) // 1 0 1
}
copysign:将另一个浮点数的符号 copy 到当前浮点数上
fn main() {
let x = 3.6_f32;
let y = -3.6_f32;
println!("{} {}", x.copysign(0.0f32), x.copysign(-0.0f32)); // 3.6 -3.6
println!("{} {}", y.copysign(0.0f32), y.copysign(-0.0f32)); // 3.6 -3.6
}
powi:计算一个浮点数的 n 次幂,n 为整数,返回浮点数
fn main() {
println!("{}", 2f32.powi(4)); // 16
}
sqrt:计算一个浮点数的平方根,返回浮点数
fn main() {
let n = 10000;
println!("{}", (n as f32).sqrt() as i32); // 100
// 还可以返回一个数的立方根
let n = 1000;
println!("{}", (n as f32).cbrt()) // 10
}
exp:以 e 为底,计算一个浮点数的指数运算,返回浮点数
fn main() {
let n = 1;
println!("{}", (n as f32).exp()); // 2.7182817
// 以 2 为底
println!("{}", (n as f32).exp2()); // 2
}
log:计算一个浮点数的对数,返回浮点数
use std::f64::consts::E;
fn main() {
let n = 1024i32;
// 整数的 ilog 方法接收一个整数作为底数,并且底数的类型和整数一致,返回值也是整数
// 浮点数的 log 方法接收一个浮点数作为底数,并且底数的类型和浮点数一致,返回值也是浮点数
println!("{} {}", n.ilog(2), (n as f32).log(2f32)); // 10 10
let n = 1023i32;
println!("{} {}", n.ilog(2), (n as f32).log(2f32)); // 9 9.99859
// int.ilog(2) 和 int.ilog(10) 可以换成 int.ilog2() 和 int.ilog10()
// float.log(2) 和 float.log(10) 可以换成 float.log2() 和 float.log10()
// 此外浮点数还提供了一个方法,针对自然对数
println!("{} {}", E.ln(), E.log(E)) // 1 1
}
hypot:计算两个点,返回浮点数组成的坐标和原点的距离,返回浮点数
fn main() {
println!("{} {}", 3f32.hypot(4f32), 6f32.hypot(8f32)); // 5 10
}
下面是一些三角函数,它们返回的都是浮点数
- sin:正弦值
- cos:余弦值
- tan:正切值
- asin:反正弦值
- acos:反余弦值
- atan:反正切值
- sinh:双曲正弦值
- cosh:双曲余弦值
- tanh:双曲正切值
- asinh:反双曲正弦值
- acosh:反双曲余弦值
- atanh:反双曲正切值
use std::f32::consts::PI;
fn main() {
// sin:正弦(对边比斜边),csc:余割(斜边比对边)
// 如果 f(x) = sin(x),那么 1 / sin(x) 得到的就是 csc(x)
println!("{}", (PI / 6f32).sin()); // 0.5
println!("{} {}", (PI / 3.0).sin(), (3f32.sqrt() / 2.0)); // 0.86602545 0.8660254
// cos:余弦(斜边比邻边),sec:正割(邻边比斜边)
// 如果 f(x) = cos(x),那么 1 / cos(x) 得到的就是 sec(x)
println!("{}", (PI / 3f32).cos()); // 0.49999997
// tan:正切(对边比邻边),cot:余切(领边比对边)
// 如果 f(x) = tan(x),那么 1 / tan(x) 得到的就是 cot(x)
println!("{}", (PI / 4f32).tan()); // 1
// 对于两个函数:y = f(x) 和 y = g(x)
// 对于任意一点 (a, b) 如果同时满足 b = f(a) 且 a = g(b),那么 f(x) 和 g(x) 互为反函数
// 比如 sin 和 asin 互为反函数,已知 sin(pi / 6) = 1 / 2,那么 asin(1 / 2) = pi / 6
println!("{} {}", (1f32 / 2f32).asin(), PI / 6f32); // 0.5235988 0.5235988
}
NAN、INFINITY
fn main() {
println!("{}", f32::NAN.is_nan()); // true
println!("{}", f32::INFINITY.is_infinite()); // true
// 如果浮点数即不是 NAN 也不是 INFINITY,返回 true
println!("{}", 3.14f32.is_finite()); // true
}
角度和弧度互转
fn main() {
// 返回的均是浮点数
println!("{}", std::f64::consts::PI.to_degrees()); // 180
println!("{}", 180f32.to_radians()); // 3.1415927
}
获取两个浮点数中的大的和小的那一个
fn main() {
let x = 3f32;
let y = 4f32;
println!("{} {}", x.max(y), if x > y {x} else {y}); // 4 4
println!("{} {}", x.min(y), if x < y {x} else {y}); // 3 3
}
以上就是整数和浮点数支持的一些方法。
如果觉得文章对您有所帮助,可以请囊中羞涩的作者喝杯柠檬水,万分感谢,愿每一个来到这里的人都生活愉快,幸福美满。
微信赞赏
支付宝赞赏