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#
暫不支持