C語(yǔ)言之整數(shù)與浮點(diǎn)數(shù)運(yùn)算的類(lèi)型轉(zhuǎn)換規(guī)則詳解
C語(yǔ)言整數(shù)與浮點(diǎn)數(shù)運(yùn)算的類(lèi)型轉(zhuǎn)換規(guī)則
在 C 語(yǔ)言中,不同數(shù)據(jù)類(lèi)型在運(yùn)算時(shí)會(huì)進(jìn)行 隱式類(lèi)型轉(zhuǎn)換。
當(dāng) 有符號(hào)整數(shù)(int
)、無(wú)符號(hào)整數(shù)(unsigned int
) 和 浮點(diǎn)型(float
、double
) 進(jìn)行運(yùn)算時(shí),編譯器會(huì)根據(jù)類(lèi)型優(yōu)先級(jí)和轉(zhuǎn)換規(guī)則自動(dòng)調(diào)整運(yùn)算的數(shù)據(jù)類(lèi)型。
1. int 和 unsigned int 參與運(yùn)算時(shí)的轉(zhuǎn)換規(guī)則
當(dāng) int
和 unsigned int
進(jìn)行運(yùn)算,運(yùn)算結(jié)果通常會(huì)轉(zhuǎn)換為 unsigned int
,原因如下:
(1)無(wú)符號(hào)優(yōu)先(Unsigned Dominance Rule)
C 語(yǔ)言規(guī)定:
如果一個(gè)操作數(shù)是 int
,另一個(gè)操作數(shù)是 unsigned int
,并且它們具有相同的寬度(如 32 位),那么 int
會(huì)被提升為 unsigned int
。
(2)示例
#include <stdio.h> int main() { int a = -5; unsigned int b = 10; if (a < b) { // a 會(huì)轉(zhuǎn)換為 unsigned int printf("a < b is true\n"); } else { printf("a < b is false\n"); } return 0; }
輸出:
a < b is false
分析:
a
是-5
(int
),b
是10
(unsigned int
)。a
在運(yùn)算前會(huì)被轉(zhuǎn)換為unsigned int
,-5
變?yōu)?4294967291
(在 32 位系統(tǒng)下)。4294967291 > 10
,所以a < b
變成false
,與直覺(jué)相反。
(3)避免問(wèn)題的方法
- 使用顯式類(lèi)型轉(zhuǎn)換
if ((int)a < (int)b) { printf("Correct comparison\n"); }
- 避免
int
和unsigned int
混用
unsigned int a = 5; unsigned int b = 10;
- 使用
size_t
進(jìn)行安全比較size_t
是無(wú)符號(hào)整數(shù),適用于數(shù)組索引等情況。
2. unsigned int 和浮點(diǎn)數(shù) (float / double) 參與運(yùn)算時(shí)的轉(zhuǎn)換規(guī)則
當(dāng) unsigned int
和 float
/ double
進(jìn)行運(yùn)算,運(yùn)算結(jié)果通常會(huì)轉(zhuǎn)換為 浮點(diǎn)型(float
/ double
),原因如下:
(1)浮點(diǎn)類(lèi)型優(yōu)先
C 語(yǔ)言規(guī)定:
如果一個(gè)操作數(shù)是 unsigned int
,另一個(gè)操作數(shù)是 float
或 double
,則 unsigned int
會(huì)自動(dòng)轉(zhuǎn)換為 float
/ double
。
(2)為什么不轉(zhuǎn)換為 unsigned int?
浮點(diǎn)數(shù)的表示范圍比
unsigned int
更大- 32 位
unsigned int
的最大值為4294967295
(2^32 - 1
)。 float
可表示~3.4 × 10^38
,double
可表示~1.8 × 10^308
。- 浮點(diǎn)數(shù)可表示的范圍遠(yuǎn)遠(yuǎn)超過(guò)無(wú)符號(hào)整數(shù),因此轉(zhuǎn)換方向是
unsigned int → float/double
,而不會(huì)反向轉(zhuǎn)換。
- 32 位
浮點(diǎn)數(shù)可以表示小數(shù),整數(shù)不行
- 例如:
5 / 2.0 = 2.5
,如果轉(zhuǎn)換為unsigned int
,會(huì)丟失.5
,變成2
,這會(huì)導(dǎo)致精度損失。 - 為了避免精度丟失,C 語(yǔ)言默認(rèn)將
unsigned int
轉(zhuǎn)換為float
或double
進(jìn)行計(jì)算。
- 例如:
(3)示例
#include <stdio.h> int main() { unsigned int a = 10; float b = 3.5; float result = a + b; // `a` 轉(zhuǎn)換為 `float` printf("Result: %f\n", result); return 0; }
輸出:
Result: 13.500000
分析:
a
(unsigned int
)被轉(zhuǎn)換為float
,變?yōu)?10.0f
。- 計(jì)算
10.0f + 3.5f = 13.5f
,結(jié)果類(lèi)型為float
。
3. 類(lèi)型轉(zhuǎn)換規(guī)則總結(jié)
運(yùn)算類(lèi)型 | 結(jié)果數(shù)據(jù)類(lèi)型 | 說(shuō)明 |
---|---|---|
int + unsigned int | unsigned int | int 先轉(zhuǎn)換為 unsigned int,可能導(dǎo)致負(fù)數(shù)變大數(shù) |
unsigned int + float | float | unsigned int 先轉(zhuǎn)換為 float,然后計(jì)算 |
unsigned int + double | double | unsigned int 先轉(zhuǎn)換為 double,然后計(jì)算 |
unsigned int * float | float | unsigned int 先轉(zhuǎn)換為 float,然后計(jì)算 |
unsigned int * double | double | unsigned int 先轉(zhuǎn)換為 double,然后計(jì)算 |
重點(diǎn)總結(jié)
int
和unsigned int
運(yùn)算時(shí),int
會(huì)被轉(zhuǎn)換為unsigned int
:- 負(fù)數(shù)可能變?yōu)槌笳龜?shù),導(dǎo)致邏輯錯(cuò)誤。
unsigned int
和float/double
運(yùn)算時(shí),unsigned int
會(huì)轉(zhuǎn)換為float/double
:- 避免精度損失,確保浮點(diǎn)計(jì)算的準(zhǔn)確性。
為了避免類(lèi)型轉(zhuǎn)換問(wèn)題,推薦:
- 統(tǒng)一變量類(lèi)型,避免
int
和unsigned int
混用。 - 明確使用
float
或double
進(jìn)行浮點(diǎn)計(jì)算,不要依賴(lài)隱式轉(zhuǎn)換。 - 使用
size_t
處理數(shù)組索引,避免unsigned int
帶來(lái)的問(wèn)題。
- 統(tǒng)一變量類(lèi)型,避免
這些規(guī)則適用于 C 語(yǔ)言,也適用于 C++ 及其他類(lèi)似的編程語(yǔ)言。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C++設(shè)計(jì)模式之迭代器模式(Iterator)
這篇文章主要為大家詳細(xì)介紹了C++設(shè)計(jì)模式之迭代器模式Iterator,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04C++實(shí)現(xiàn)LeetCode(111.二叉樹(shù)的最小深度)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(111.二叉樹(shù)的最小深度),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單反彈球消磚塊游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單反彈球消磚塊游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05Qt數(shù)據(jù)庫(kù)應(yīng)用之超級(jí)自定義委托
Qt中需要用到自定義委托的情形很多,比如提供下拉框選擇,進(jìn)度條展示下載進(jìn)度啥的,默認(rèn)的單元格是沒(méi)有這些效果的,需要自己?jiǎn)为?dú)用委托的形式來(lái)展示。本文將為大家介紹Qt中如何進(jìn)行超級(jí)自定義委托,需要的可以參考一下2022-03-03C語(yǔ)言銀行系統(tǒng)課程設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言銀行系統(tǒng)課程設(shè)計(jì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01簡(jiǎn)單掌握Linux系統(tǒng)中fork()函數(shù)創(chuàng)建子進(jìn)程的用法
fork()函數(shù)只能在類(lèi)Unix系統(tǒng)下使用,因?yàn)樾枰雞nistd頭文件,這里我們就來(lái)簡(jiǎn)單掌握Linux系統(tǒng)中fork()函數(shù)創(chuàng)建子進(jìn)程的用法,需要的朋友可以參考下2016-06-06C++ 數(shù)據(jù)結(jié)構(gòu)之kmp算法中的求Next()函數(shù)的算法
這篇文章主要介紹了C++ 數(shù)據(jù)結(jié)構(gòu)之kmp算法中的求Next()函數(shù)的算法的相關(guān)資料,需要的朋友可以參考下2017-06-06