Scalar Types

ในภาษา rust ตัวแปรที่ถูกประกาศขึ้นมาเพื่อใช้งานนั้นจะต้องระบุชนิดของข้อมูลที่ใช้เก็บค่าไว้ด้วย โดยค่าเหล่านี้จะเป็นค่าที่ไม่สามารถแยกย่อยลงไปได้อีกแล้ว

Scalar Data Type ในภาษา Rust จะมีด้วยกัน 4 ประเภท คือ

  1. Integers
  2. Floating-point numbers
  3. Booleans
  4. Characters

ทีนี้เรามาลงรายละเอียดแต่ละตัวกัน

1. จำนวนเต็ม (Integers)

เป็นประเภทข้อมูลที่ไว้ใช้สำหรับตัวแปรประเภท ตัวเลขที่ไม่มีส่วนประกอบที่เป็นเศษส่วน โดยจะแบ่งออกเป็น 2 แบบ คือ

Signed (i) เป็นชนิดข้อมูลที่ใช้เก็บค่าจำนวนเต็มบวกและเต็มลบ
Unsigned (u) เป็นชนิดข้อมูลที่ใช้เก็บค่าจำนวนเต็มบวกเท่านั้น

fn main() {
  let count:i8 = 0;

  println!("The value of count is: {count}");
}

syntex

โดยตัวแปรแบบ integers นั้นจะต้องมีการระบุ size ที่ชัดเจน ตามตารางด้านล่าง

LengthSignedUnsigned
8-biti8u8
16-biti16u16
32-biti32u32
64-biti64u64
128-biti128u128
archisizeusize

ส่วนขอบเขตของข้อมูลก็จะเป็นดังนี้
Signed:
i8: เก็บค่าได้ -128 ถึง 127
i16
: เก็บค่าได้ -32,768 ถึง 32,767
i32
: เก็บค่าได้ -2,147,483,648 ถึง 2,147,483,647
i64
: เก็บค่าได้ -9,223,372,036,854,775,808 ถึง 9,223,372,036,854,775,807

Unsigned:
u8: จำนวนเต็มบวก 8 บิต เก็บค่าได้ 0 ถึง 255
u16
: จำนวนเต็มบวก 16 บิต เก็บค่าได้ 0 ถึง 65,535
u32
: จำนวนเต็มบวก 32 บิต เก็บค่าได้ 0 ถึง 4,294,967,295
u64
: จำนวนเต็มบวก 64 บิต เก็บค่าได้ 0 ถึง 18,446,744,073,709,551,615

ข้อดีของการใข้งาน Unsigned นั้น คือ เก็บค่าจำนวนเต็มบวกได้มากกว่า Signed ในขนาดเดียวกัน ในบางเคส unsigned ทำงานได้เร็วกว่า Signed ด้วยซ้ำ

แต่ตัวมันก็มีข้อเสียเหมือนกัน นั่นคือ ไม่สามารถเก็บค่าจำนวนเต็มลบได้ และอาจเกิด Overflow ง่ายกว่า Signed เพราะฉนั้นเลือกประเภทการใช้งานให้เหมาะสมกับงานที่ใช้

นอกจากนี้เรายังสามารถเก็บจำนวนเต็มในรูปแบบของ  integer literals ได้อีกด้วย ตัวอย่างตามตารางนี้

Number literalsExample
Decimal98_222
Hex0xff
Octal0o77
Binary0b1111_0000
Byte (u8 only)b'A'

2. จำนวนทศนิยม (Floating-point numbers)

ใน rust นั้น จะมีการเก็บจำนวนของ ทศนิยม 2 ประเภทด้วยกัน นั่นคือ f32 และ f64 โดยค่าเริ่มต้นของประเภทนี้จะเป็น f64 เนื่องจาก CPU รุ่นใหม่ๆ ใช้ base 64 bit กันเป็นปกติแล้ว

LenghtSizePresision
f32±1.7 x 10^387
f64±9.2 x 10^1816
fn main() {
  let price: f64 = 200.45;

  println!("The value of price is: {price}");
}

syntex

การเลือกใช้ f32 หรือ f64:

  • ใช้ f32 เมื่อ:
    • ต้องการประหยัดหน่วยความจำ
    • ต้องการประสิทธิภาพ และสามารถยอมรับการสูญเสียความแม่นยำเล็กน้อย
    • ทำงานกับค่าที่อยู่ในช่วงและความแม่นยำของ f32
  • ใช้ f64 เมื่อ:
    • ต้องการความแม่นยำสูง โดยเฉพาะสำหรับการคำนวณที่ต้องการตัวเลขทศนิยมที่แม่นยำ
    • ทำงานกับตัวเลขขนาดใหญ่หรือเล็กมากที่อยู่นอกช่วงของ f32

3. บูลีน (Booleans)

เหมือนกับภาษาอื่นๆ ที่เคยเขียนกัน ประเภท Booleans ใน Rust มีค่าที่เป็นไปได้ 2 ค่า: true และ false โดย booleans นั้นมีขนาด 1 ไบต์เท่านั้น

fn main() {
  let open: bool = true;
  
  println!("The value of open is: {open}");
}

syntex


4. ตัวอักษร (Characters)

ตัวสุดท้าย คือ ตัวอักษร แค่ 1 ตัวอักษร เช่น 'a', 'B', '€' โดยตัวอักษรนั้นจะอยู่ภายใต้ Single Quote ซึ่งจะตรงข้ามกับ String ที่จะใช้ Double Quote

fn main() {
  let character: char = 'a';

  println!("The value of character is: {character}");
}

syntex


Compound Types

นอกเหนือตัวแปรที่เป็นแบบ scalar type แล้ว ในภาษา rust ยังมีประเภทของข้อมูล อีกประเภทหนึ่ง ที่ใช้สำหรับระบุประเภทของข้อมูลที่มีการประกอบกันมากกว่า 1 ตัว ซึ่งจะมีอยู่ 2 ประเภทคือ tuples และ arrays

1.Tuples Type

เป็นวิธีทั่วไปในการจัดกลุ่มค่าจำนวนหนึ่งที่มีประเภทต่างกัน รวมเข้าไว้ด้วยกัน เพื่อให้รวมกันอยู่ภายใต้ตัวแปรเดียวกัน

Tuples จะมีความยาวคงที่ เมื่อประกาศแล้ว มันจะไม่สามารถขยายหรือลดขนาดได้อีกแล้ว

ตัวอย่างการประกาศ

fn main() {
    let tup: (i32, f64, u8) = (500, 6.4, 1);
}

syntex

ทีนี้ หากเราต้องการเข้าถึงตัวแปร tuples สามารถทำได้โดยการ binding ตัวแปรให้กับค่าแต่ละค่า เช่น

fn main() {
    let tup = (500, 6.4, 1);

    let (x, y, z) = tup;

    println!("The value of y is: {y}");
}

binding variables

หรือจะอ้างอิง index จากตัวแปรที่เก็บค่านั้นไว้

fn main() {
    let x: (i32, f64, u8) = (500, 6.4, 1);

    let five_hundred = x.0;

    let six_point_four = x.1;

    let one = x.2;
}

refer index in tuple variable


2.Array Type

อีกหนึ่งวิธีในการรวมค่าหลายๆ ค่า เข้าไว้ด้วยกัน คือ การใช้ array แต่ค่าข้างใน array จะต้องเป็นค่าประเภทเดียวกันเท่านั้น ซึ่งต่างจาก tuple ที่จะเก็บค่าได้หลากหลายกว่า

แน่นอนว่า array ใน Rust จะ fixed ความยาว ซึ่งการใช้งานก็เหมาะกับการใช้งานแบบ stack มากกว่าที่จะเป็น heap (Stack/Heap Memory) หรือจะใช้เมื่อต้องการ fixed ความยาวสูงสุดให้คงที่เสมอ

ถ้าหากต้องการเก็บข้อมูลแบบไม่ Fixed ก็จะไปใช้ตัวแปรแบบ vector ที่เป็นตัว standard library ที่ Rust มีไว้ให้

fn main() {
    let a = [1, 2, 3, 4, 5];
}

array syntex

เรายังสามารถระบุประเภทและขนาดของ array ได้ด้วยการ ใช้ square brackets ([])

let a: [i32; 5] = [1, 2, 3, 4, 5];

array type syntex

สามารถระบบค่าเริ่มต้นที่มีค่าเหมือนก็ได้

let a = [3; 5];

// จะมีค่าเท่ากับ
let a = [3, 3, 3, 3, 3];

initialize an array

การเข้าถึงองค์ประกอบของ array

fn main() {
    let a = [1, 2, 3, 4, 5];

    let first = a[0];
    let second = a[1];
}

Accessing Array Elements

ทั้งหมดนี้เป็น Data Types เบื้องต้นในภาษา Rust จริงๆ ยังมี Data Types รูปแบบอื่นอยู่ด้วย แต่มันจะอยู่ในรูปแบบของ library ให้เราเรียกใช้มากกว่า