為什麼除法時必須在數字周圍包裹一個 uint() 並且有提示?
為什麼除法時必須在數字周圍包裹一個 uint() 並且有提示?
當我按照下面的程式碼顯示時,我沒有收到任何錯誤,並且程式碼工作正常。
function doMath() public pure returns(uint256){ return 100/2; }
但是當我按照下面的程式碼顯示時,我得到一個錯誤:
返回類型rational_const 不能顯式轉換為類型…
function doMath() public pure returns(uint256){ return 100/3; }
uint(100)
我知道如果我像這樣包裝兩者,錯誤就會消失uint(3)
。但我的問題是為什麼我需要將它們包裝起來uint()
以使編譯器不拋出錯誤?
這是一個非常好的問題。它涉及一個可能不太為人所知的細節,即使它已記錄在案(Rational 和 Integer Literals):
數字文字表達式保持任意精度,直到它們被轉換為非文字類型(即通過將它們與非文字表達式一起使用或通過顯式轉換)。這意味著計算不會溢出,除法不會在數字文字表達式中截斷。
例如,雖然中間結果甚至不適合機器字長,但
(2**800 + 1) - 2**800
結果為常量1
(類型為)。uint8
此外,.5 * 8
結果為整數4
(儘管在兩者之間使用了非整數)。換句話說,文字數字類似於
100
and3
不是uint
s 或任何其他整數類型。相反,Solidity 為它們提供了一種特殊的內部類型,並且僅使用文字的表達式在編譯時以任意精度進行評估。只有當您分配它們或在具有非文字的表達式中使用它們時,它們才會轉換為實際的整數類型。另一個重要的事實是,您可以混合使用整數和有理字面量,並且仍然保留這些屬性。so
100/3
仍然是文字類型 whileuint(100)/3
或all 強制轉換100/uint(3)
為. 對於,運算符是整數除法,它會默默地丟棄小數部分。uint(100)/uint(3)``uint``uint``/
所以結果
uint(100)/uint(3)
已經是uint
,你可以在沒有額外轉換的情況下返回它。100/3
是文字類型,編譯器不會靜默截斷文字。相反,它要求您對uint
(ieuint(100/3)
) 進行顯式轉換,以表明這確實是您想要發生的事情。不需要它,100/2
因為結果是一個不需要截斷的整數文字,編譯器可以將其隱式轉換為uint
.