StarknetAstro

StarknetAstro

03_Cairo中的標量類型(felt、integer、boolean、float)

03_Cairo 中的標量類型 (felt,integer,boolean,float)#

此文章使用的 Cairo 編譯器版本:2.0.0-rc0。因為 Cairo 正在快速更新,所以不同版本的語法會有些許不同,未來將會將文章內容更新到穩定版本。

felt252#

felt252 是 Cairo 中基礎類型,代表一個存儲槽,未指定變量類型的字面量默認類型都是 felt252。felt252 可以是負數或者是 0,它的取值範圍是:

-X < felt < X, where X = 2^{251} + 17* 2^{192} + 1

任何在這個取值範圍內的值都可以存儲在 felt252 中。注意⚠️:並不是 -(2^251) ~ (2^251 - 1)

felt252 既可以存整數,也可以存儲字符串,下面👇是存儲整數和字符串的例子:

use debug::PrintTrait;

fn main() {
	// let關鍵字聲明,直接用字面量賦值,默認類型應該是felt252
    let x: felt252 = 5;
    let y: felt252 = 'ppppppppppppppppppppppppppp';
    let z: felt252 = 'ppppppppppppppppppppppppppp99999999999999'; // 溢出
    x.print();
}

注意⚠️:是 252 不是 256,而且 felt 後面接其他數字或者不接都會編譯報錯,例如felt256 felt

短字符串#

短字符串用單引號表示,並且長度不能超過 31 個字符。短字符串本質上是 felt252 類型,只是表現形式為字符串,計算機通過 ASCII 協議將字符轉換成數字。短字符串長度不能超過 31 個字符,本質上是不能超過 felt252 的最大值。

let mut my_first_initial = 'C';

felt252 與整型的區別#

Cairo1.0 中,felt252 不支持除法運算,也不支持取餘,整型可以。

以下是Cairo 0.1中關於 felt 的描述:

flet 是 field elements 的縮寫,可以翻譯為域元素。felt252 與整型的區別主要體現在除法運算上。當出現不能整除的運算時,例如 7/3,整型運算的結果通常是 2,但是 felt252 不是。felt252 會始終滿足 x3 = 7 這個等式,由於只能是整數,所以 x3 的值將會是一個巨大的整數,以至於溢出,溢出後的值剛好是 7。

在 Cairo1.0 中,felt252 被禁止使用除法

use debug::PrintTrait;

fn main() {
    let x = 7 / 3;
    x.print();
}

// 以上代碼將會的到如下錯誤
error: Trait has no implementation in context: core::traits::Div::<core::felt252>
 --> f_felt252.cairo:4:13
    let x = 7 / 3;
            ^***^

Error: failed to compile: src/f_felt252.cairo

整型#

核心庫中包含了這些整型變量: u8, u16, u32 (usize), u64, u128, and u256。他們都是用 felt252 實現的,並且自帶整數溢出檢測,溢出後觸發 Panic 錯誤。聲明整型變量時,如果不指定變量類型,默認就是 felt252 類型,代碼如下:

let y = 2;

指定 u8, u16 等,需要標明變量的類型:

let x:u8 = 2;

其中 u256 類型比較複雜,創建 u256 類型需要使用其他類型來構建。u256 在核心庫裡是一個結構體,其中兩個字段 high 和 low 都是 u128 類型,因為一個存儲槽(felt252)無法裝下 u256 類型的數據,所以需要拆成兩個存儲槽來存儲。

let z: u256 = u256 { high: 0, low: 10 }

其中涉及到 高地址段低地址段 的概念,大家感興趣可以查詢相關資料。

運算符#

整型支持大多數運算符,並且自帶溢出檢測,支持如下:

fn test_u8_operators() {
	// 計算
    assert(1_u8 + 3_u8 == 4_u8, '1 + 3 == 4');
    assert(3_u8 + 6_u8 == 9_u8, '3 + 6 == 9');
    assert(3_u8 - 1_u8 == 2_u8, '3 - 1 == 2');
    assert(1_u8 * 3_u8 == 3_u8, '1 * 3 == 3');
    assert(2_u8 * 4_u8 == 8_u8, '2 * 4 == 8');
    assert(19_u8 / 7_u8 == 2_u8, '19 / 7 == 2');
    assert(19_u8 % 7_u8 == 5_u8, '19 % 7 == 5');
    assert(231_u8 - 131_u8 == 100_u8, '231-131=100');

	// 比較
    assert(1_u8 == 1_u8, '1 == 1');
    assert(1_u8 != 2_u8, '1 != 2');
    assert(1_u8 < 4_u8, '1 < 4');
    assert(1_u8 <= 4_u8, '1 <= 4');
    assert(5_u8 > 2_u8, '5 > 2');
    assert(5_u8 >= 2_u8, '5 >= 2');
    assert(!(3_u8 > 3_u8), '!(3 > 3)');
    assert(3_u8 >= 3_u8, '3 >= 3');
}

另外,u256 同樣也支持這些運算符:

use debug::PrintTrait;

fn main() {
    let x:u256 = u256{high:3, low: 3};
    let y:u256 = u256{high:3, low: 3};

    let z = x + y;
    assert(z == 2 * y, 'z == 2 * y');
    assert(0 == x - y, '0 == x - y');
    assert(1 == x / y, '0 == x - y');
    assert(0 == x % y, '0 == x % y');

    assert(x == y, 'x == y');
    assert(x <= y, 'x <= y');
    assert(x >= y, 'x <= y');
    assert(x - 1 < y, 'x - 1 < y');
    assert(x + 1 > y, 'x + 1 >= y');
    assert(x != y - 1, 'x != y');
}

Boolean#

可以使用如下方式進行聲明

let is_morning:bool = true;
let is_evening:bool = false;

Float#

暫不支持

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。