精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

計算機系統對數值類型的編碼、運算、轉換原理介紹4

jf_78858299 ? 來源:元閏子的邀請 ? 作者:元閏子 ? 2023-05-09 16:31 ? 次閱讀

數值類型轉換

數值類型間的轉換,可以分成 2 類: 寬轉換 (Widening Conversion)和 窄轉換 (Narrowing Conversion)。

寬轉換指往表示范圍更廣的類型轉換,比如從 int 到 long、從 long 到 float;窄轉換則相反。

整型間轉換

(1)寬轉換

整型間的寬轉換不會產生溢出,無符號整數場景,高位補零;有符號整數場景,高位補符號位。

// C++
int main() {
    int8_t i1 = 100;
    cout << "int8_t  i1: " << bitset<8>(i1) << endl;
    cout << "int16_t i1: " << bitset<16>((int16_t) i1) << endl;

    int8_t i2 = -100;
    cout << "int8_t  i2: " << bitset<8>(i2) << endl;
    cout << "int16_t i2: " << bitset<16>((int16_t) i2) << endl;

    uint8_t i3 = 200;
    cout << "uint8_t  i3: " << bitset<8>(i3) << endl;
    cout << "uint16_t i3: " << bitset<16>((uint16_t) i3) << endl;
    return 0;
}
// 輸出結果
int8_t  i1: 01100100
int16_t i1: 0000000001100100
int8_t  i2: 10011100
int16_t i2: 1111111110011100
uint8_t  i3: 11001000
uint16_t i3: 0000000011001000

(2)窄轉換

整型間的窄轉換直接進行高位截斷,只保留低 n 位。比如 16 位的 int16 轉換為 8 位的 int8,直接保留 int16 類型值的低 8 位作為轉換結果。

// C++
int main() {
    int16_t i1 = 200;
    cout << "int16_t i1: " << bitset<16>(i1) << endl;
    cout << "int8_t  i1: " << bitset<8>((int8_t) i1) << endl;

    int16_t i2 = -200;
    cout << "int16_t i2: " << bitset<16>(i2) << endl;
    cout << "int8_t  i2: " << bitset<8>((int8_t) i2) << endl;

    uint16_t i3 = 300;
    cout << "uint16_t i3: " << bitset<16>(i3) << endl;
    cout << "uint8_t  i3: " << bitset<8>((uint8_t) i3) << endl;
    return 0;
}
// 輸出結果
int16_t i1: 0000000011001000
int8_t  i1: 11001000
int16_t i2: 1111111100111000
int8_t  i2: 00111000
uint16_t i3: 0000000100101100
uint8_t  i3: 00101100

(3)無符號整數與有符號整數間的轉換

無符號整數與有符號整數間的轉換規則是:

  • 如果兩者二進制位數一致,比如 int8uint8 的轉換,則二進制數值不變,只是改變編碼方式;
  • 如果位數不一致,比如 int16uint8 的轉換,則二進制數值,先按照寬轉換或窄轉換規則轉換,再改變編碼方式。
// C++
int main() {
    uint8_t i1 = 200;
    cout << "uint8_t i1, decimal: " << +i1 << ", binary: " << bitset<8>(i1) << endl;
    cout << "int8_t  i1, decimal: " << +(int8_t) i1 << ", binary: " << bitset<8>((int8_t) i1) << endl;

    int16_t i2 = -300;
    cout << "int16_t i2, decimal: " << +i2 << ", binary: " << bitset<16>(i2) << endl;
    cout << "uint8_t i2, decimal: " << +(uint8_t) i2 << ",  binary: " << bitset<8>((uint8_t) i2) << endl;
    return 0;
}
// 輸出結果
uint8_t i1, decimal: 200, binary: 11001000
int8_t  i1, decimal: -56, binary: 11001000
int16_t i2, decimal: -300, binary: 1111111011010100
uint8_t i2, decimal: 212,  binary: 11010100

整數與浮點數間轉型

(1)寬轉換

整型到浮點數類型的轉換這一方向,為寬轉換:

  • 如果浮點數的精度,能夠表示整數,則正常轉換。
  • 如果浮點數精度,無法表示整數,則需要近似,會導致精度丟失。
// Java
public static void main(String[] args) {
    int i1 = 1234567;
    System.out.printf("int i1: %d, float i1: ", i1);
    System.out.println((float) i1);

    int i2 = 123456789;
    System.out.printf("int i2: %d, float i2: ", i2);
    System.out.println((float) i2);
}
// 輸出結果
int i1: 1234567, float i1: 1234567.0
int i2: 123456789, float i2: 1.23456792E8

上述例子中,i2=123456789 超過 float 類型能夠表示的精度,所以為近似后的結果 1.23456792E8。

那么,為什么 123456789 會近似為 1.23456792E8

要解釋該問題,首先要把它們轉換成二進制表示:

public static void main(String[] args) {
    ...
    System.out.println("int i2:   " + int2BinaryStr(i2));
    System.out.println("float i2: " + float2BinaryStr((float) i2));
}
// 輸出結果
int i2:   00000111010110111100110100010101
float i2: 01001100111010110111100110100011

接下來,我們根據 IEEE 浮點數的編碼規則,嘗試將 int i2 轉換成 float i2

  1. int i2 的二進制 ,可以寫成 ,對應到 的形式,可以確認 s = 0,E = 26,M = 1.11010110111100110100010101。
  2. float 類型中 k = 8,有,,得出 e = 153,按 k 位無符號編碼表示為 。
  3. 同理,由 ,但由于 float 類型的 n = 23,而 m 一共有 26 位,因此需要按照 round-to-even 規則,對 0.11010110111100110100010101進行近似,保留 23 位小數,得到 0.11010110111100110100011,所以 m 為
  4. 最后,將 s、e、m 按照 float 單精度的編碼格式組合起來,就是 ,轉換成十進制,就是 1.23456792E8。

(2)窄轉換

浮點數類型到整型的轉換這一方向,為窄轉換:

  • 如果浮點數的整數部分,能夠用整型表示,則直接舍去小數,保留整數部分。
  • 如果超出了整型范圍,則結果為該整型的最大/最小值。
// Java
public static void main(String[] args) {
    float f1 = 12345.123F;
    System.out.print("float f1: ");
    System.out.print(f1);
    System.out.printf(",  int f1: %d\\n", (int) f1);

    float f2 = 1.2345E20F;
    System.out.print("float f2: ");
    System.out.print(f2);
    System.out.printf(",  int f2: %d\\n", (int) f2);

    float f3 = -1.2345E20F;
    System.out.print("float f3: ");
    System.out.print(f3);
    System.out.printf(", int f3: %d\\n", (int) f3);
 }
// 輸出結果
float f1: 12345.123,  int f1: 12345
float f2: 1.2345E20,  int f2: 2147483647
float f3: -1.2345E20, int f3: -2147483648

浮點數間轉型

(1)寬轉換

單精度 float 到 雙精度 double 為寬轉換,不會出現精度丟失的問題。

對于 ,規則如下:

  • s 保持不變。
  • 在 E 保持不變的前提下,因為 float 的 k = 8,而 double 的 k = 11,所以兩者的 e 會有所不同。
  • 在 M 保持不變的前提下,float 的 n = 23,而 double 的 n =52,所以 m 需要低位補 52 - 23 = 29 個 0。
// Java
public static void main(String[] args) {
    float f1 = 1.2345E20F;
    System.out.print("float  f1: ");
    System.out.print(f1);
    System.out.print(", double f1: ");
    System.out.println((double) f1);

    System.out.println("float  f1: " + float2BinaryStr(f1));
    System.out.println("double f1: " + double2BinaryStr((double) f1));
}
// 輸出結果
float  f1: 1.2345E20, double f1: 1.2344999897320129E20
float  f1: 01100000110101100010011011010000
double f1: 0100010000011010110001001101101000000000000000000000000000000000

圖片

(2)窄轉換

doublefloat 為窄轉換,會存在精度丟失問題。

如果 double 值超出了 float 的表示范圍,則轉換結果為 Infinity

// Java
public static void main(String[] args) {
    double d1 = 1E200;
    System.out.print("double d1: ");
    System.out.println(d1);
    System.out.print("float d1: ");
    System.out.println((float) d1);

    double d2 = -1E200;
    System.out.print("double d2: ");
    System.out.println(d2);
    System.out.print("float d2: ");
    System.out.println((float) d2);
 }
// 輸出結果
double d1: 1.0E200
float d1: Infinity
double d2: -1.0E200
float d2: -Infinity

如果 double 值還在 float 的表示范圍內,則按照如下轉換規則:

  • s 保持不變。
  • 在 E 保持不變的前提下,因為 float 的 k = 8,而 double 的 k = 11,所以兩者的 e 會有所不同。
  • 對于 M,因為 float 的 n = 23,而 double 的 n = 52,所以轉換到 float 之后,需要進行截斷,只保留高 23 位。
// Java
public static void main(String[] args) {
    double d1 = 3.267393471324506;
    System.out.print("double d1: ");
    System.out.println(d1);
    System.out.print("float  d1: ");
    System.out.println((float) d1);
    System.out.println("double d1: " + double2BinaryStr(d1));
    System.out.println("float  d1: " + float2BinaryStr((float) d1));
}
// 輸出結果
double d1: 3.267393471324506
float  d1: 3.2673936
double d1: 0100000000001010001000111001111100110000001101000000010101110110
float  d1: 01000000010100010001110011111010

圖片

最后

本文花了很長的篇幅,深入介紹了計算機系統對數值類型的編碼、運算、轉換的底層原理。

數值類型間的轉換是最容易出現隱藏 bug 的地方 ,特別是無符號整數與有符號整數之間的轉換。所以,很多現代的編程語言,如 Java、Go 等都不再支持無符號整數,根除了該隱患。

另外,浮點數的編碼方式,注定它只能精確表示一小部分的數值范圍,大部分都是近似,所以才有了不能用等號來比較兩個浮點數的說法。

數值類型雖然很基礎,但使用時一定要多加小心。希望本文能夠加深你對數值類型的理解,讓你寫出更健壯的程序。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 二進制
    +關注

    關注

    2

    文章

    794

    瀏覽量

    41600
  • 計算機
    +關注

    關注

    19

    文章

    7425

    瀏覽量

    87722
  • 編程
    +關注

    關注

    88

    文章

    3595

    瀏覽量

    93604
收藏 人收藏

    評論

    相關推薦

    計算機系統結構

    計算機系統結構
    發表于 05-09 19:03

    什么是計算機系統、計算機硬件和計算機軟件?

    第一章 計算機系統概論1. 什么是計算機系統、計算機硬件和計算機軟件?硬件和軟件哪個更重要?解:P3計算機系統:由
    發表于 07-22 09:06

    什么是計算機系統?硬件和軟件哪個更重要?

    第一章計算機系統概論1 .什么是計算機系統計算機硬件和計算機軟件?硬件和軟件哪個更重要?解: P3計算機系統:由
    發表于 07-26 07:18

    計算機系統中的軟件系統

    專用計算機現代計算機運算速度最高可達每秒幾萬億次幾十億次幾億次幾萬次計算機輔助制造是計算機應用領域之一其英文縮寫是所謂的信息是指基本素材非數值
    發表于 09-13 07:22

    嵌入式計算機系統概述

    硬件子系統和軟件子系統組成的,通過運行程序來協同工作計算機硬件:基本的計算機硬件系統運算器、控
    發表于 12-22 06:08

    簡單介紹微型計算機的組成

    你了解自己的計算機?或者知道單片機的組成嗎?這一小節主要簡單介紹微型計算機的組成,以及微型計算機系統經常用到的概念,包括組成、工作過程、工作原理、
    發表于 01-10 07:11

    計算機系統概論

    1.1 計算機系統簡介1.2 計算機的基本組成1.3 計算機硬件的主要技術指標1.4 本書結構
    發表于 04-11 09:31 ?0次下載

    微型計算機系統

             微型計算機系統與傳統的計算機系統一樣,也是由硬件系統和軟件系統兩大部分組成的。2.1
    發表于 03-03 08:31 ?0次下載

    什么是計算機系統的容錯性

    什么是計算機系統的容錯性             所謂容錯是指在故障存在的情況下計算機系統不失效,仍然能夠正常工作的特性
    發表于 01-08 13:49 ?1628次閱讀

    深入理解計算機系統數值類型

    計算機系統中,整數可以分成 無符號(unsigned)整數 和 有符號(signed)整數 兩大類,這之下,按照類型表示的 bit 位大小,又可細分成 8 位的 char/byte/int8
    的頭像 發表于 08-19 15:17 ?1150次閱讀

    計算機系統對數值類型編碼、運算、轉換原理介紹1

    。正因太熟悉,我們往往不會深究它們的底層原理。因為平時的工作中,知道個大概,也夠用了。 但,在某些業務場景下,比如金融業務,數值運算不準確會帶來災難性的后果。這時,你就必須清楚數值類型
    的頭像 發表于 05-09 16:30 ?1137次閱讀
    <b class='flag-5'>計算機系統</b><b class='flag-5'>對數值</b><b class='flag-5'>類型</b>的<b class='flag-5'>編碼</b>、<b class='flag-5'>運算</b>、<b class='flag-5'>轉換</b>原理<b class='flag-5'>介紹</b>1

    計算機系統對數值類型編碼、運算、轉換原理介紹2

    。正因太熟悉,我們往往不會深究它們的底層原理。因為平時的工作中,知道個大概,也夠用了。 但,在某些業務場景下,比如金融業務,數值運算不準確會帶來災難性的后果。這時,你就必須清楚數值類型
    的頭像 發表于 05-09 16:31 ?878次閱讀
    <b class='flag-5'>計算機系統</b><b class='flag-5'>對數值</b><b class='flag-5'>類型</b>的<b class='flag-5'>編碼</b>、<b class='flag-5'>運算</b>、<b class='flag-5'>轉換</b>原理<b class='flag-5'>介紹</b>2

    計算機系統對數值類型編碼、運算、轉換原理介紹3

    。正因太熟悉,我們往往不會深究它們的底層原理。因為平時的工作中,知道個大概,也夠用了。 但,在某些業務場景下,比如金融業務,數值運算不準確會帶來災難性的后果。這時,你就必須清楚數值類型
    的頭像 發表于 05-09 16:31 ?794次閱讀
    <b class='flag-5'>計算機系統</b><b class='flag-5'>對數值</b><b class='flag-5'>類型</b>的<b class='flag-5'>編碼</b>、<b class='flag-5'>運算</b>、<b class='flag-5'>轉換</b>原理<b class='flag-5'>介紹</b>3

    計算機系統中的關鍵組件有哪些

    計算機系統中,關鍵組件的協同工作構成了其強大的數據處理和運算能力。這些組件不僅決定了計算機的性能,還影響著用戶的使用體驗。以下是對計算機系統中關鍵組件的詳細闡述,包括它們的定義、功能
    的頭像 發表于 07-15 18:18 ?1294次閱讀

    微處理器如何控制計算機系統

    微處理器,作為計算機系統的核心部件,承擔著控制整個計算機系統運行的重要任務。它不僅是計算機運算中心,還是控制中心,負責執行程序指令、處理數據以及協調
    的頭像 發表于 08-22 14:21 ?444次閱讀