初心者向けの Solidity チュートリアル: 10. 制御フロー、Solidity を使用して挿入ソートを実装する
この講義では、 solidityの制御フローを紹介し、次に、 solidityを使用して挿入ソート ( InsertionSort ) を実装する方法について説明します。このプログラムは、単純そうに見えて、実はバグが書きやすいプログラムです。
制御フロー
Solidityの制御フローは他の言語の制御フローと似ており、主に次のものが含まれます。
- if-else
function ifElseTest(uint256 _number) public pure returns(bool){
if(_number == 0){
return(true);
}else{
return(false);
}
}
- forループ
function forLoopTest() public pure returns(uint256){
uint sum = 0;
for(uint i = 0; i < 10; i++){
sum += i;
}
return(sum);
}
- while ループ
function whileTest() public pure returns(uint256){
uint sum = 0;
uint i = 0;
while(i < 10){
sum += i;
i++;
}
return(sum);
}
- do-while ループ
function doWhileTest() public pure returns(uint256){
uint sum = 0;
uint i = 0;
do{
sum += i;
i++;
}while(i < 10);
return(sum);
}
- 三項演算子三項演算子は、 Solidityで3 つのオペランドを受け入れる唯一の演算子ですルール条件? true 条件の式: false 条件の式。この演算子は、if ステートメントのショートカットとしてよく使用されます。
// 三元运算符 ternary/conditional operator
function ternaryTest(uint256 x, uint256 y) public pure returns(uint256){
// return the max of x and y
return x >= y ? x: y;
}
また、使用できるcontinue (次のループにすぐに入る) キーワードとBreak (現在のループから飛び出す) キーワードもあります。
Solidityを使用した挿入ソートの実装
以前に書きました: Solidityを使用して挿入アルゴリズムを作成する場合、 90% 以上の人が間違いを犯します。
挿入ソート
ソート アルゴリズムによって解決される問題は、**[2, 5, 3, 1]** などの順序のない数値のセットを小さいものから大きいものへと並べることです。挿入ソート ( InsertionSort ) は最も単純なソート アルゴリズムであり、多くの人が最初に学ぶアルゴリズムでもあります。考え方は非常にシンプルで、前から後ろに向かって、それぞれの数字とその前の数字を比較し、前の数字より小さい場合は位置を入れ替えます。回路図:
Pythonコード
まず、挿入ソートの Python コードを見てみましょう。
# Python program for implementation of Insertion Sort
def insertionSort(arr):
for i in range(1, len(arr)):
key = arr[i]
j = i-1
while j >=0 and key < arr[j] :
arr[j+1] = arr[j]
j -= 1
arr[j+1] = key
return arr
Solidityに書き換えるとBUG が発生します。
合計 8 行のPythonコードで挿入ソートを完了できます。これは非常に簡単です。次に、それをSolidityコードに書き直し、それに応じて関数、変数、ループなどを変換します。必要なコードはわずか 9 行です。
// 插入排序 错误版
function insertionSortWrong(uint[] memory a) public pure returns(uint[] memory) {
for (uint i = 1;i < a.length;i++){
uint temp = a[i];
uint j=i-1;
while( (j >= 0) && (temp < a[j])){
a[j+1] = a[j];
j--;
}
a[j+1] = temp;
}
return(a);
}
次に、変更をリミックスに加えて実行し、 **[2, 5, 3, 1] と入力します。ブーム!バグがあります**! 長い間変更を加えてきましたが、バグは見つかりませんでした。Googleで「Solidity 挿入ソート」を検索したところ、インターネット上にあるSolidityで書かれた挿入アルゴリズムのチュートリアルがすべて間違っていることがわかりました。たとえば、「Solidity での比較なしの
ソート」、「Remix のデコードされた出力エラーの内容」などです。
正しいソリッド性挿入ソート
数時間かかり、Dapp-Learningコミュニティの友人の協力を得て、最終的にバグを発見しました。Solidityで最も一般的に使用される変数タイプは、正の整数であるuintですが、負の値が取得された場合は、アンダーフローエラーが報告されます。挿入アルゴリズムでは、変数j が**-1** となり、エラーが発生する場合があります。ここで、 j が負の値にならないように1
を加算する必要があります。正しいコード:
// 插入排序 正确版
function insertionSort(uint[] memory a) public pure returns(uint[] memory) {
// note that uint can not take negative value
for (uint i = 1;i < a.length;i++){
uint temp = a[i];
uint j=i;
while( (j >= 1) && (temp < a[j-1])){
a[j] = a[j-1];
j--;
}
a[j] = temp;
}
return(a);
}
実行後の結果:
要約する
今回の講義では、 solidityの制御フローを紹介し、solidityを使った挿入ソートを書きました。簡単そうに見えますが、実はとても難しいことなのです。こういった小さなバグのせいで、プロジェクトは毎月、数千万ドル、さらには数億ドルを失っています。基本をマスターし、継続的に練習することによってのみ、より優れたSolidityコードを作成できるようになります。