資料型別的問題

2021-09-05 13:37:41 字數 2516 閱讀 5838

好久沒有上來寫點什麼東西了,也有一段時間沒有到部落格堂撥客園上面來采風了,今天一上來就看到這個文章:

資料型別的bug還是???

裡面羅列了一些問題,也許我能略解一二。比如說問題二:

dim ss as double

ss = 400*1000

在vb6中,報越界!!

ss = 400*100000沒有異常

其實是這樣的,vb6裡面對於常數,如果沒有帶資料型別標誌符(例如#)或者小數點,就認為是整數。而對於實際上是什麼整數,則根據最小化原則,認為400和1000同為16位帶符號整形。而數值計算結果的資料型別和運算元中表示範圍最大的相一致(其實大部分語言都是這麼定義的。ps:對於vb6及以下版本,似乎沒有應用常量傳播,要到計算裡面才會出錯),很明顯400*1000的計算結果超出16位帶符號整形的表示範圍,報越界。而400*100000裡面後者被認為是32位帶符號數值,因此計算結果也是32位帶符號數值,所以不會越界。

請注意,大部分語言的計算過程是有乙個中間計算結果的,這個結果跟最終承載變數沒有關係,而跟該語言的運算法則相關。在本例當中無論ss被定義為double、long還是別的數值型別,都必然會引發越界,這是由vb6裡面的語言定義所引起的。而中間計算結果要經過乙個轉換過程才能夠得到最終變數的資料型別,一般的基本資料型別之間都有「隱式」轉換,有的是強制轉換,這個一般由語言本身所定義。例如在vb6裡面,幾乎所有數值型別之間都能夠自由的進行隱式轉換,但是在c#裡面,浮點數轉換為整形數字的時候就必須要強制轉換。

當然,從某種角度來講,所有數值型別之間能夠自由的隱式是vb6語言定義本身的缺陷,因為這樣可能會引發很多「看不見」的問題。但是這實際上是vb6語言本身的定義,而不是設計人員無意識的或者不期望的結果,所以我寧願稱之為fault也不願意說是bug。

可是大壞蛋卻說.net裡面:

double ss;

int firstint = 2147483646;

int secondint = 2;

ss = firstint + secondint;

console.writeline(ss);

結果:ss = -2147483648

似乎對這個現象有點意見。首先,還是那個原因,計算是有中間結果的,中間結果的型別在這裡仍然是int。其次,要追溯c語言本身的處理方式,在c語言裡面不會對整形的上下界超界產生任何疑問,甚至不會報錯。因為這個被認為是c語言的「特性」之一,c#「號稱」繼承了c/c++,那自然也會盡可能繼承這些傳統習慣,因此他就作為語法規範裡面的一部分了,無可厚非。而事實上這也不是.net framework的功勞,而僅僅是c#的定義而已。因為在vb.net裡面,這會產生異常的。因為在c#的編譯器對整數加減法使用的是不帶檢驗的il指令,而vb.net則使用的是待檢驗的il指令。比如c#使用的是add指令,而vb.net則使用的是add.ovf指令。當然,這是在最普遍的**編寫方式,以及預設的語言引數下面而言的。

如果有什麼疑問,請嘗試下述**:

int ss;

int firstint = 2147483646;

int secondint = 2;

ss = firstint + secondint;

console.writeline(ss);

呵呵,現在再請沒有疑問的嘗試下述**:

int ss = int.maxvalue + 2;

回過頭來我們再看看第乙個問題:

dim ss as double

ss = 194268.02 – 194268

肉眼可以判斷結果為0.02,而vb中計算的結果:ss = 0.199999999895226e-02

ss = 1.2 - 1 vb計算的結果為:0.2

要知道這個問題的答案,我們首先要看看這裡的浮點數到底是什麼浮點數。在.net framework裡面(以及vb/vc等)遵循的是ieee標準,那麼為什麼0.02不是0.02了呢?其實這個在ieee裡面可以找到乙個快速的解答。那麼為什麼後面乙個計算會是正確的呢?那其實是因為「精度」足夠,使得你認為它就是0.2。事實上ieee浮點數永遠不可能精確等於2的n次冪相加所構成的數值(比如1.375 = 20 + 2-2 + 2-3,我「簡稱」這種數字為「可被2整除的數字」。),除非ieee更改了他的標準。(關於ieee浮點數的定義可以參考這裡。)順帶給出double的1.2和0.2的十六進製制編碼:

1.2 = ieee_double(3ff3 3333 3333 3333)

0.2 = ieee_double(3fc9 9999 9999 999a)

而1.2-1的運算結果卻是 ieee_double(3fc9 9999 9999 9998),看到了嗎?其實1.2 - 1並不等於0.2的。而事實上ieee浮點運算即使是在「可被2整除」的數字之間進行,通常都會有誤差的,這主要源於精度丟失。前面的1.2 - 1的誤差並不屬於這個範疇,這主要是由於運算元本身無法被精確表示而造成的(雖然也有精度丟失的原因)。可以說精度不丟失的情況是相當特殊的,比如說完全相等的兩個數相加減,乘、除以2的整倍或者正負1以及0,和0或者「非數字」之間的計算,等等。

所以說這些問題千萬不要往ms的頭上扣,也不是ms所能夠改變得了的。

資料型別問題

powerdesigner中mandatory意為 not null 數值型別 int和integer是同義詞,完全一致。powerdesigner欄位的預設值設定,和charset設定 mysql的索引問題 主鍵本身就具有索引,設定索引可以減少訪問時間,最好在需要進行查詢的字段上新增索引 uniq...

資料型別的轉換問題

自動資料型別轉換 數值型 從小到大 整型 byte short int long 浮點型 float double float自動轉為double型別可能存在精度損失 整型 浮點型 直接在整數後邊補個.0 可能存在精度損失問題 byte short int long float double 字元型...

資料型別問題整理

typeof中,undefined 如果這個值未定義。在使用var宣告變數但是未對其加以初始化時,這個變數的值就是undefined.var message alert message undefined true null,從邏輯標度來看,null表示空指標。這也是為什麼typeof null 會...