最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Mit_6301_2021_中文個(gè)人翻譯_第一課_Static Checking

2023-08-16 01:31 作者:宋劍寒  | 我要投稿

# 第一章:Static Checking


**課程目標(biāo)**


本節(jié)課有兩個(gè)目標(biāo):


* 靜態(tài)類(lèi)型


* 優(yōu)秀軟件的三大特點(diǎn)


## 冰雹序列


冰雹序列從一個(gè)自然數(shù) n 開(kāi)始,如果 n 是偶數(shù),那么它的下一個(gè)數(shù)為 n/2,如果 n 是奇數(shù),那么下一個(gè)數(shù)為 3n + 1;冰雹序列會(huì)不停迭代直到這個(gè)數(shù)變?yōu)?1 為止。


以下是一些冰雹序列的例子。


``````

2, 1

3, 10, 5, 16, 8, 4, 2, 1

4, 2, 1

2^n, 2^(n-1) , … , 4, 2, 1

5, 16, 8, 4, 2, 1

7, 22, 11, 34, 17, 52, 26, 13, 40, …? (尚未結(jié)束)

``````


由于存在奇數(shù)的 3n + 1 法則,冰雹序列在最終停止之前會(huì)反復(fù)的上升下降。但是根據(jù)推測(cè),任意的自然數(shù) n 起始的冰雹序列,最終都會(huì)達(dá)到 1 而停止,但這仍只是個(gè)猜想,沒(méi)有嚴(yán)格的證明。另外一提,冰雹序列之所以叫做冰雹序列,是因?yàn)楸⒃谠茖又蟹e攢重量時(shí),會(huì)在云層中上下跳動(dòng),直到它積攢了足夠的重量能夠落到地上去。


## 如何計(jì)算冰雹序列


這里給出一些計(jì)算冰雹序列的 Java 代碼和 Python 代碼,大家可以比較以下它們的區(qū)別


```java

// Java

int n = 3;

while (n != 1) {

? ? System.out.println(n);

? ? if (n % 2 == 0) {

? ? ? ? n = n / 2;

? ? } else {

? ? ? ? n = 3 * n + 1;

? ? }

}

System.out.println(n);

? ?

```


```python

# Python

n = 3

while n != 1:

? ? print(n)

? ? if n % 2 == 0:

? ? ? ? n = n / 2

? ? else:

? ? ? ? n = 3 * n + 1

? ? ? ?

print(n)

```


這里有一些值得注意的點(diǎn):


* Java 和 Python 的基礎(chǔ)語(yǔ)法是十分相似的:


? 比如 ``while`` 和 ``if`` 的使用是是非相似的


* Java 在每行的某位需要使用分號(hào)作為結(jié)尾


* Java 在使用 ``if`` 和 ``while`` 做判斷的時(shí)候,需要把條件用括號(hào)括起來(lái)


* Java 使用中括號(hào)而不是縮進(jìn)來(lái)標(biāo)識(shí)語(yǔ)句塊。Java 不關(guān)注你是否使用空格來(lái)區(qū)分語(yǔ)句直接的關(guān)系,但你還是應(yīng)當(dāng)使用縮進(jìn)來(lái)表明語(yǔ)句塊之間的關(guān)系。因?yàn)榫幊桃彩且环N交流,你不止需要面對(duì)編譯器,還需要面對(duì)閱讀你代碼的普通人。


? 而人,是需要這些縮進(jìn)的,我們以后還會(huì)提到這點(diǎn)。


## 類(lèi)型


Java 和 Python 在語(yǔ)法上的最重要的區(qū)別在于變量 ``n`` 的聲明,在 Java 中我們聲明了它的類(lèi)型 ``int``


**類(lèi)型** 涵蓋了從屬這些類(lèi)型的值和定義在這些值上的運(yùn)算


Java 有幾種基本數(shù)據(jù)類(lèi)型,以下是幾個(gè)例子:


* ``int`` (類(lèi)似于 5 或者 -200 的整數(shù),但是它有其上下限 ±2^31,或者說(shuō) ±20億)

* ``long`` (用于更大的整數(shù),±2^63)

* ``boolean`` (只有兩個(gè)值,``true`` 和 ``false``)

* ``double`` (用于浮點(diǎn)數(shù))

* ``char`` (用于單個(gè)字母,比如 ``A`` 和 ``$`` )


Java 還有引用類(lèi)型,比如:


* ``String`` 表示 ``char`` 的序列,就像 ``python`` 的 字符串 一樣

* ``BigInteger`` 表示任意大小的整數(shù),就像 ``python`` 中的整數(shù)一樣


在 Java 中,我們習(xí)慣上用小寫(xiě)來(lái)表示基本數(shù)據(jù)類(lèi)型,用大寫(xiě)來(lái)表示引用類(lèi)型


定義在這些類(lèi)型上的運(yùn)算,實(shí)際上是一些接受輸入,產(chǎn)生輸出的函數(shù)(有時(shí)會(huì)改變傳入的值),運(yùn)算使用時(shí)的語(yǔ)法千差萬(wàn)別,但是我們?nèi)耘f視它們?yōu)楹瘮?shù)。以下是一些 Python 或者 Java 中運(yùn)算的使用示例:


* 運(yùn)算符:``a + b`` 會(huì)調(diào)用操作 ``+ : int x int -> int`` 。(``+`` 是這個(gè)運(yùn)算的名字,``int x int`` 描述了兩個(gè)輸入,箭頭的右邊的 ``int`` 描述了輸出。)

* 實(shí)例方法:``bigint1.add(bigint2)`` 調(diào)用運(yùn)算:``add: BigInteger x BigInteger -> BigInteger`` 。

* 類(lèi)方法:``Math.sin(theta)`` 調(diào)用運(yùn)算 ``sin: double -> double`` 這里 ``Math`` 不是一個(gè)對(duì)象,而是一個(gè)類(lèi),這個(gè)類(lèi)中包含了 ``sin`` 函數(shù)。


我們對(duì)比一下 Java 中的 ``str.length()`` 和 Python 中的 ``len(str)`` 。它們的功能都是輸入一個(gè)字符串,返回字符串的長(zhǎng)度,只在語(yǔ)法上有一點(diǎn)區(qū)別。


有一些操作符是重載過(guò)的,這使得它們可以在不同的數(shù)據(jù)類(lèi)型中使用而不需要改變形式。Java 中用于基本數(shù)據(jù)類(lèi)型計(jì)算的操作符都是經(jīng)過(guò)重載的,比如``+, -, *, /`` 。Java 中方法也是可以被重載的,大多數(shù)的編程語(yǔ)言都可以實(shí)現(xiàn)不同程度的重載。


## 靜態(tài)類(lèi)型


Java 是 **靜態(tài)類(lèi)型語(yǔ)言**:所有變量的類(lèi)型在編譯期間(程序運(yùn)行前)就已經(jīng)確定,因此編譯器也可以通過(guò)變量的類(lèi)型來(lái)確定變量表達(dá)式結(jié)果的類(lèi)型。如果 ``a`` 和 ``b`` 被聲明為 ``int`` , 編譯器就會(huì)認(rèn)為 ``a + b`` 也是 ``int`` 類(lèi)型。Eclipse 在你還在編寫(xiě)程序的同時(shí)就會(huì)進(jìn)行類(lèi)型檢查,所以你能夠在程序編寫(xiě)階段就發(fā)現(xiàn)很多錯(cuò)誤。


在 **動(dòng)態(tài)類(lèi)型語(yǔ)言** 中,這種類(lèi)型檢查會(huì)被推遲倒程序運(yùn)行時(shí)執(zhí)行,Python 就是動(dòng)態(tài)類(lèi)型語(yǔ)言。


**靜態(tài)檢查**意味著在編譯時(shí)期就檢查bugs。Bugs 是編程的萬(wàn)惡之首。本課程的很多部分都在試圖教會(huì)你如何在代碼中消除 bug,而靜態(tài)檢查就是你最先看到的部分。靜態(tài)類(lèi)型可以減少你程序中的一大類(lèi)錯(cuò)誤:準(zhǔn)確的說(shuō),就是數(shù)據(jù)類(lèi)型的不匹配。如果你的代碼像下面一樣:


```java

"5" * "6"

```


這行代碼嘗試將兩個(gè)字符串相乘,靜態(tài)類(lèi)型語(yǔ)言就會(huì)發(fā)現(xiàn)這個(gè)錯(cuò)誤,并且在你還在編寫(xiě)程序的時(shí)候就提出來(lái)。


## 在動(dòng)態(tài)類(lèi)型語(yǔ)言中支持靜態(tài)類(lèi)型


盡管 Python 是一個(gè)動(dòng)態(tài)類(lèi)型語(yǔ)言,Python 3.5 以及更新的版本已經(jīng)支持使用 [type hints](https://peps.python.org/pep-0484/) 來(lái)在代碼中支持靜態(tài)類(lèi)型,代碼示例:


```python

# Python function declared with type hints

def hello(name:str)->str:

? ? return 'Hi, ' + name

```


可以使用像 [Mypy](https://mypy-lang.org/) 檢查器來(lái)在你還沒(méi)有運(yùn)行程序之前來(lái)檢查類(lèi)型錯(cuò)誤


在動(dòng)態(tài)類(lèi)型語(yǔ)言中添加靜態(tài)類(lèi)型反應(yīng)了軟件工程領(lǐng)域一個(gè)非常普遍的認(rèn)知:靜態(tài)類(lèi)型對(duì)于開(kāi)發(fā)和維持一個(gè)大型軟件系統(tǒng)是非常重要的。事實(shí)上本書(shū)的剩余部分或者說(shuō)整個(gè)課程都在致力于說(shuō)明這一認(rèn)知的理由。


與 Java 這種從誕生之初就是靜態(tài)類(lèi)型的語(yǔ)言不同,在動(dòng)態(tài)類(lèi)型語(yǔ)言中添加靜態(tài)類(lèi)型可以實(shí)現(xiàn)一種新的編程類(lèi)型:漸進(jìn)類(lèi)型。也就是代碼中的一部分是靜態(tài)類(lèi)型聲明,一部分是動(dòng)態(tài)類(lèi)型聲明。漸進(jìn)類(lèi)型能夠讓你從一個(gè)小的不完整的原型系統(tǒng)開(kāi)始,開(kāi)發(fā)為一個(gè)大型的穩(wěn)固的可維護(hù)的系統(tǒng)的過(guò)程中提供更加順暢的體驗(yàn)。


## 靜態(tài)檢查、動(dòng)態(tài)檢查、不檢查


讓我們來(lái)仔細(xì)思考一下以下三種編程語(yǔ)言能夠提供給我們的自動(dòng)檢查:


* **靜態(tài)檢查** :在程序還沒(méi)有運(yùn)行之前就能夠發(fā)現(xiàn) bug

* **動(dòng)態(tài)檢查** :在程序執(zhí)行時(shí)才發(fā)現(xiàn) bug

* **不檢查** :該編程語(yǔ)言完全不檢查任何 bug,你必須自己找到 bug,或者接受一個(gè)錯(cuò)誤的答案


無(wú)需多言,靜態(tài)檢查優(yōu)于動(dòng)態(tài)檢查,動(dòng)態(tài)檢查又優(yōu)于不檢查


以下是一些經(jīng)驗(yàn)之談來(lái)表明你能在不同的檢查類(lèi)型下能夠發(fā)現(xiàn)哪些 bug:


**靜態(tài)檢查**能夠發(fā)現(xiàn):


* 語(yǔ)法錯(cuò)誤,比如額外的標(biāo)點(diǎn)符號(hào)或者拼寫(xiě)錯(cuò)誤。即使是動(dòng)態(tài)類(lèi)型的語(yǔ)言也會(huì)檢查這種類(lèi)型的錯(cuò)誤,比如 Python 在你運(yùn)行程序之前就檢查縮進(jìn)錯(cuò)誤。

* 拼寫(xiě)錯(cuò)誤比如``Math.sine(2)`` (正確的拼寫(xiě)是 ``sin`` )

* 錯(cuò)誤的參數(shù):``Math.sin(30, 20)``?

* 錯(cuò)誤的參數(shù)類(lèi)型:``Math.sin("30")``?

* 錯(cuò)誤的返回類(lèi)型:函數(shù)聲明的返回類(lèi)型是 ``int`` ,而實(shí)際返回的卻是 ``return "30"``?


**動(dòng)態(tài)檢查**能夠發(fā)現(xiàn):


* 非法參數(shù)值:對(duì)于整數(shù)相除的表達(dá)式 ``x / y`` 只有當(dāng) ``y`` 為 0 的時(shí)候,才會(huì)出現(xiàn)除零錯(cuò)誤,當(dāng) ``y`` 不為 0 時(shí),這個(gè)表達(dá)式的值是正確且確定的。所以在這個(gè)例子中,除零錯(cuò)誤是一個(gè)動(dòng)態(tài)錯(cuò)誤,而不是一個(gè)靜態(tài)錯(cuò)誤。

* 不合法的類(lèi)型轉(zhuǎn)換:有些特定的值是不能轉(zhuǎn)換為其他數(shù)據(jù)類(lèi)型的。比如:```Integer.valueOf("hello")`` 是一個(gè)動(dòng)態(tài)錯(cuò)誤,因?yàn)?``hello`` 不能被轉(zhuǎn)換為一個(gè)十進(jìn)制整數(shù)。``Integer.valueOf("8000000000")`` 也是一個(gè)動(dòng)態(tài)錯(cuò)誤,因?yàn)?80 億超出了 ``int`` 類(lèi)型能夠接收的范圍。

* 超出索引范圍,例如在字符串索引時(shí)使用負(fù)數(shù)或者過(guò)大的索引

* 調(diào)用實(shí)例方法時(shí),對(duì)象引用為 ``null`` ,(``null`` 和 Python 中的 ``None`` 類(lèi)似)


靜態(tài)檢查可以檢測(cè)跟變量類(lèi)型有關(guān)的錯(cuò)誤,但是通常不能檢測(cè)這個(gè)變量類(lèi)型特定值相關(guān)的錯(cuò)誤。靜態(tài)檢查保證了變量具有其變量類(lèi)型的值,但是具體的值只有等到程序運(yùn)行期間才得以知曉。所以如果某個(gè)錯(cuò)誤只跟這個(gè)類(lèi)型的特定值有關(guān),比如除零錯(cuò)誤,那么編譯器就不會(huì)找到靜態(tài)錯(cuò)誤。


動(dòng)態(tài)檢查傾向于找到那些具體值所引發(fā)的錯(cuò)誤。


## 你或許不知道的:基本數(shù)據(jù)類(lèi)型并不是真正的數(shù)學(xué)數(shù)字


Java 和 其他一些編程語(yǔ)言中有一個(gè)經(jīng)典的陷阱:它們的基本數(shù)據(jù)數(shù)字類(lèi)型在極端情況下并不像我們?cè)谌粘?shù)學(xué)中使用的數(shù)字一樣。這會(huì)導(dǎo)致一些應(yīng)該被動(dòng)態(tài)檢查的錯(cuò)誤,沒(méi)有被檢測(cè)出。


* 整數(shù)除法:``5 / 2`` 并不會(huì)返回一個(gè)小數(shù),它會(huì)返回一個(gè)被截?cái)嗟恼麛?shù)。這常常會(huì)導(dǎo)致我們的程序產(chǎn)生錯(cuò)誤的答案,并且程序還不會(huì)檢測(cè)出動(dòng)態(tài)錯(cuò)誤。


* 整數(shù)溢出:``int`` 和 ``long`` 實(shí)際上是有限的整數(shù)集,具有上限和下限。當(dāng)你向這兩種數(shù)據(jù)類(lèi)型中填充一個(gè)過(guò)大的正整數(shù)或者過(guò)小的負(fù)整數(shù)時(shí)會(huì)發(fā)生什么呢?答案是產(chǎn)生溢出,并且是悄悄的溢出,它會(huì)返回一個(gè)類(lèi)型范圍內(nèi)的值,但不是正確的值。


? ```java

? int a = 2147483647;

? a = fun(a);

? public static int fun(int a) {

? ? ? return a + 1;

? }

? ```


* 浮點(diǎn)類(lèi)型中的特殊值:浮點(diǎn)類(lèi)型像 ```double``` 擁有幾種特殊值。```NaN``` (Not a Number),```POSITIVE_INFINITY``` , ```NEGATIVE_INFINITY``` 。當(dāng)你在```double``` 類(lèi)型上做一些操作時(shí),比如除零或者對(duì)負(fù)數(shù)開(kāi)根號(hào),你將不會(huì)得到一個(gè)動(dòng)態(tài)錯(cuò)誤,而是獲得以上的幾種特殊值。如果你把這些值當(dāng)作是中間值進(jìn)行計(jì)算,你最終可能會(huì)得到一個(gè)奇怪的答案。


## 練習(xí)


接下來(lái)我們來(lái)做一些練習(xí)來(lái)鞏固知識(shí),以下這些有 bug 的代碼,它們的錯(cuò)誤會(huì)被靜態(tài)檢查捕獲還是動(dòng)態(tài)檢查還是捕獲不到呢?


```java

int n = -5;

if (n) {

? System.out.println("n is a positive integer");

}

```


```java

int big = 200000; // 200,000

big = big * big;? // big should be 40 billion now

```


```java

double probability = 1/5;

```


```java

int sum = 0;

int n = 0;

int average = sum/n;

```


```java

double sum = 7;

double n = 0;

double average = sum/n;

```


Mit_6301_2021_中文個(gè)人翻譯_第一課_Static Checking的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
多伦县| 洛川县| 永靖县| 新民市| 府谷县| 迭部县| 高雄市| 新乐市| 隆子县| 台安县| 遵义市| 军事| 社旗县| 光泽县| 两当县| 星子县| 曲水县| 塔城市| 义乌市| 深州市| 霍林郭勒市| 尼木县| 绵阳市| 太仓市| 永济市| 信阳市| 漾濞| 金乡县| 永康市| 鹤庆县| 景德镇市| 乐陵市| 克什克腾旗| 蒙阴县| 清徐县| 修水县| 天全县| 九龙城区| 阳谷县| 景泰县| 怀宁县|