ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

RUST 学习日记 第8课 ——类型转换

2021-06-30 13:32:37  阅读:395  来源: 互联网

标签:类型转换 浮点数 整数 let println f64 转为 日记 RUST


RUST 学习日记 第8课 ——类型转换


0x00 回顾

上一节讲解了字面量和常见一些运算符,还记得上节课最后留了一个练习题吗。

小明有5块钱,小红有3块5,小明和小红总共有多少钱呢?

你们成功运行出结果了吗,这节咱们介绍下Rust的类型转换。

0x01 类型转换(Type Cast)

与其它语言不同,在Rust中,整数和浮点数不能再一起做运算。先看下示例:

     let o = 5;
    let p = 3.5;

    dbg!(o + p);

上面代码的输出结果是什么呢?如果你有C,Java等语言基础,那么你肯定会说上面的结果是8.5。但是在Rust中编译器会报错,如下图所示。

cannot add a float to an integer,不能把浮点数加到整数上。在Rust中不会帮你隐式的转换格式。

0x02 类型转换表达式(Type Cast Expressions)

语法 类型转换表达式 : Expression as TypeNoBounds

类型转换使用as操作符来表示。它可以将as左边的类型强制转换为右边的类型。示例如下:

let o = 5;
let q = o as f64;
dbg!(q);

代码执行结果:

[src\main.rs:13] q = 5.0

不可变变量o默认的类型是i32,将其强制转换为f64的类型复制给不可变变量q,结果变为了5.0,类型变为f64浮点型。

0x03 旧题重解

咱们得知as可以类型转换,那么题目的答案就显而易见了。

// 先将 o 转为 f64类型,再做加法
dbg!(o as f64 + p);

代码执行结果:

[src\main.rs:16] o as f64 + p = 8.5

现在的程序就不会报错了,结果也计算出来了。

0x04 类型转换规则(Coercion Rule)

as可以被用于显示的强制类型转换。在数值进行强制转换时可能会存在精度问题。这里我再介绍下数值间强制转换的一些注意事项。

1、在两个相同长度大小的整数间进行有无符号强制转换,请注意符号位和整数范围。例如:u8 -> i8

下面是扩展知识。要理解这条规则,需要先明白在计算机中是如何存储数值的。

在计算机中存在有符号和无符号数两种数值,有符号数有三种表示方法,即原码、反码和补码。三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位,三种表示方法各不相同。在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理。

上面提到了有符号数3个概念,原码,反码,补码。下面以+1-1为例,简单解释下这三个概念,以8位整数类型为例。有符号数的最高位是符号位,0表示正数,1表示负数,因此+1的原码就是0000 0001-1的原码就是1000 0001对于正数来说,其原码,反码,补码都相同负数的反码,则是对除符号位的每一位都取反(有关取反操作上节已经介绍了)。那么-1的反码就是1111 1110补码就是在反码的基础上再加1-1的补码就是1111 1111。如果反码在加1操作后,8位变为了9位,则将会舍弃最高位。

Rust强转的示例代码如下:

    let a: i8 = 1;
    let b: i8 = -1;
    println!("[有符号数] {} 转为[无符号数]: {}, 转换后的二进制为 {:08b}", a, a as u8, a as u8);
    println!("[有符号数] {} 转为[无符号数]: {}, 转换后的二进制为 {:08b}", b, b as u8, b as u8);

    let a: u8 = 1;
    let b: u8 = 255;
    println!("[无符号数] {} 转为[有符号数]: {}, 转换后的二进制为 {:08b}", a, a as i8, a as i8);
    println!("[无符号数] {} 转为[有符号数]: {}, 转换后的二进制为 {:08b}", b, b as i8, b as i8);

代码执行结果:

[有符号数] 1 转为[无符号数]: 1, 转换后的二进制为 00000001
[有符号数] -1 转为[无符号数]: 255, 转换后的二进制为 11111111
[无符号数] 1 转为[有符号数]: 1, 转换后的二进制为 00000001
[无符号数] 255 转为[有符号数]: -1, 转换后的二进制为 11111111

2、较长位数的整数转换为较短位数的整数时会发生截断。例如:i16 -> i8

16位整数300转为8位整数会发生什么?计算机会将300的二进制高位舍弃,只保留低位,这就是截断,会发生精度损失。示例如下:

    let a: i16 = 300;
    println!("{} 的 二进制为:{:016b}", a, a);
    // 发生数据截断,保留了低位,截断了高位
    println!("16位整数 {} 转为 8位整数:{},其二进制为: {:016b}", a, a as i8, a as i8);

代码执行结果:

300 的 二进制为:0000000100101100
16位整数 300 转为 8位整数:44,其二进制为: 0000000000101100

3、较短位数的整数转换为较长位数的整数时会有下面两种情况。例如:i8 -> i16

  • 如果该值是无符号数,则高位使用0填充
  • 如果该值是有符号数,则高位使用符号数填充

示例代码:

    let a: u8 = 45;
    // a 是8位整数,但是输出时的格式我加了0填充,可以忽略前8位的显示
    println!("8位无符号整数 {} 的 二进制为:{:016b}", a, a);
    println!("8位无符号整数 {} 的 转为16位整数的二进制为:{:016b}", a, a as u16);

    let b: i8 = -121;
    // b 是8位整数,但是输出时的格式我加了0填充,可以忽略前8位的显示
    println!("8位有符号整数 {} 的 二进制为:{:016b}", b, b);
    println!("8位有符号整数 {} 的 转为16位整数的二进制为:{:016b}", a, b as i16);

代码执行结果:

8位无符号整数 45 的 二进制为:0000000000101101
8位无符号整数 45 的 转为16位整数的二进制为:0000000000101101
8位有符号整数 -121 的 二进制为:0000000010000111
8位有符号整数 45 的 转为16位整数的二进制为:1111111110000111

4、浮点数转换为整数时,将会直接舍弃小数位,保留整数部分。另外还有下面3点要注意:

  • 如果浮点数是NAN,转为整数时将会返回0
  • 如果当前的浮点数值大于所转换的整数类型的最大值,则将返回该整数类型的最大值
  • 如果当前的浮点数值小于所转换的整数类型的最大值,则将返回该整数类型的最小值

示例代码:

    // NAN 相当于 0.0 / 0.0
    let a: f64 = f64::NAN;
    // 正无穷大 +∞
    let b: f64 = f64::INFINITY;
    // 负无穷大 -∞
    let c: f64 = f64::NEG_INFINITY;

    println!("NAN 转换为整数的值为 {}", a as i32);
    println!("+∞ 转换为整数的值为 {}", b as i32);
    println!("-∞ 转换为整数的值为 {}", c as i32);

    // 其它情况,直接舍弃小数,不会进行四舍五入
    let d: f64 = 54.5;
    let e: f64 = 65.1;

    println!("浮点数 {} 转换为整数 {}", d, d as i32);
    println!("浮点数 {} 转换为整数 {}", e, e as i32);

代码执行结果:

NAN 转换为整数的值为 0
+∞ 转换为整数的值为 2147483647
-∞ 转换为整数的值为 -2147483648
浮点数 54.5 转换为整数 54
浮点数 65.1 转换为整数 65

5、整数转换为浮点数时,可能会发生数据浮动

  • 如果发生数据浮动,将遵循roundTiesToEven模式。(数据round到到相邻最近的浮点数据上。如果两个浮点数据都一样近,则round到最后一位是偶数的浮点数据上)
  • 如果转换时发生溢出,则将会输出为无穷大(∞)

PS:在数值类型中,溢出仅发生在 u128 as f32的值大于或者等于f32::MAX + (0.5 ULP)时。

示例代码:

    let a: i32 = 5;
    println!("{} 转为浮点数 {}", a, a as f64);

    // 溢出
    let b: u128 = u128::MAX;
    println!("{} 转为浮点数 {}", b, b as f32);

代码执行结果:

5 转为浮点数 5
340282366920938463463374607431768211455 转为浮点数 inf

6、f32浮点数可以完美无损的转换为f64浮点数。

示例代码:

    let a: f32 = 98.0;
    println!("f32浮点数 {} 转为 f64浮点数 {}", a, a as f64);

代码执行结果:

f32浮点数 98 转为 f64浮点数 98

7、f32浮点数转换f64浮点数时,可能会发生数据浮动。

  • 如果发生数据浮动,将遵循roundTiesToEven模式。(数据round到到相邻最近的浮点数据上。如果两个浮点数据都一样近,则round到最后一位是偶数的浮点数据上)
  • 如果转换时发生溢出,则将会输出为无穷大(∞)

示例代码:

    // 数据浮动,注意精度
    let a: f64 = 9045.213123;
    println!("f64浮点数 {} 转为 f32浮点数 {}", a, a as f32);

    // 溢出
    let b: f64 = f64::MAX;
    println!("f64浮点数 {} 转为 f32浮点数 {}", b, b as f32);

代码执行结果:

f64浮点数 9045.213123 转为 f32浮点数 9045.213
f64浮点数 179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 转为 f32浮点数 inf

8、布尔型转为整数型。true转为整数的值是1false转为整数的值是0。Rust不允许由整数转为布尔型

示例代码:

    let a = false;
    let b = true;
    println!("{} 转为 整数为 {}", a, a as i32);
    println!("{} 转为 整数为 {}", b, b as i32);    

代码执行结果:

false 转为 整数为 0
true 转为 整数为 1

9、u8类型转换为char类型

  • 仅支持u8型整数转为char类型
  • char类型转为整数时,如果整数位数长度不够,则将发生截断,同上面说的第3点

示例代码:

    // u8转为char
    let a: u8 = 97;
    println!("u8型整数 {} 转为 char 为{}", a, a as char);

    // char转整数
    // 笑脸图标
    let b: char = '\u{1F604}';
    println!("char型 {} 转为i32的值为:{}, 其二进制为 {:032b}", b, b as i32, b as i32);
    println!("char型 {} 转为i16的值为:{}, 其二进制为 {:032b}", b, b as i16, b as i16);
    println!("char型 {} 转为i8的值为:{}, 其二进制为 {:032b}", b, b as i8, b as i8);

代码执行结果:

u8型整数 97 转为 char 为a
char型 

标签:类型转换,浮点数,整数,let,println,f64,转为,日记,RUST
来源: https://blog.csdn.net/a1595901624/article/details/118358851

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有