Tunoblog - NooB
คณิตศาสตร์ ดนตรี คำศัพท์ คอมพิวเตอร์ และ อื่น ๆ อีก (มั่วมาก) มาก
Sunday, November 25, 2007
Monday, June 11, 2007
หัดออกเสียงแบบชาว California: เดาเสียง s z จากตัวสะกด
ไม่ได้เขียนอะไรใน blog นี้ประมาณเวลาตั้งครรภ์ได้ ตอนนี้ใกล้จะกลับไทยแล้ว ก็ขอเขียนซักหน่อยละกัน :P
เนื่องด้วยภาษาอังกฤษที่เราเรียนในเมืองไทย เน้นให้อ่านออก เขียนได้ แต่ไม่ได้ให้ออกเสียงถูก พอมีโอกาสมาอยู่เมืองนอกแล้ว มันก็น่าจะฝึกส่วนที่ขาดหายไปใช่มะ แล้วก็สำเนียงภาษาอังกฤษของคนแถวนี้ (California) เค้าถือว่ามาตรฐานของ American English ด้วย ไหน ๆ มาอยู่ Stanford แล้ว ก็ลงเรียนวิชา Pronunciation ซะเลย :D ตอนแรกก็ไม่นึกหรอกว่ามันจะน่าสนใจขนาดนี้ เรียน ๆ ไป รู้สึกว่ามีสิ่งที่ไม่รู้เยอะแฮะ (แต่เรียนจบคอร์สแล้ว สำเนียงก็เหมือน ๆ เดิมอะนะ)
คิดว่าหลาย ๆ คนที่เรียนอังกฤษในเมืองไทยคงยังไม่เคยรู้เรื่องพวกนี้ ก็เลยจะเอามาฝากกันนี่แหละ (American English อย่างเดียวนะ)
เสียง s กับ z
คิดว่าทุกคนคงรู้อยู่แล้วว่า s มีเสียงเหมือน "ซ" หรือ "ส" ในภาษาไทย ส่วนตัว z เนี่ย ถึงเราจะไม่มีตัวอักษรที่ออกเสียงเหมือนกัน แต่คิดว่าตัวนี้ไม่น่าจะเป็นปัญหากับคนไทย ถ้าใครไม่รู้ว่า z ออกเสียงยังไง ก็ทำเสียง s (ไม่ได้ออกจากกล่องเสียง) แล้วพยายามเติมเสียงจากกล่องเสียง มันก็จะเป็น z เอง (อันนี้ง่าย)
แล้วเมื่อไหร่ใช้ s เมื่อไหร่ใช้ z หละ?
จะว่าไปมันก็เป็นเรื่องแปลก (คนที่รู้ก็คงไม่แปลกหรอก) ที่คำที่สะกดด้วยตัว s อ่านออกมาเป็น z เยอะมาก กฎสำหรับออกเสียง z เวลาเห็นตัว s ก็มีหลัก ๆ คือ
- s ใน -s ที่ใช้เป็นตัวสุดท้ายของคำ ตามหลังเสียง voiced consonant (ไว้จะพูดถึงอีกที) เช่น pens
- s ใน -es ท้ายคำที่เป็นพหูพจน์ (ให้ออกเสียงว่า อิซซ ด้วย z)
- คำว่า is his Ms.
- -sn't -sm เช่น anarchism
- ss
- s ที่ขึ้นต้นคำ และไม่ได้ตามด้วย h, ch
- s ที่ลงท้าย prefix เช่น misapprehend disavow
- s หลังสระเสียงสั้น (ยกเว้น is his Ms.) เช่น this promise pus
- s ใน -s ที่ใช้เป็นตัวสุดท้ายของคำ ตามหลังเสียง voiceless consonant
- s หลังพยัญชนะ หน้าสระ เช่น insensitive absinthe lapse alongside forsake
- -s? เมื่อ ? เป็นพยัญชนะ voiceless เช่น anarchist
- คำ 1 พยางค์ที่ลงท้ายด้วย -ase กับ -oose
- s หลังสระเสียงยาวใน verb มักจะเป็น z เช่น realise refuse lose ease appease please แต่ loose grease lease cease crease increase decrease decease ใช้เสียง s
- s หลังสระเสียงยาวในคำที่ไม่มีรูป verb มักจะเป็น s เช่น dose verbose close(adj) แต่ cheese disease ใช้เสียง z
- คำบางคำอ่านต่างกันเมื่อเป็น noun กับ verb เช่น use กับ house ใช้ s เมื่อเป็น noun ใช้ z เมื่อเป็น verb
- close ที่แปลว่าใกล้ (adjective กับ adverb) ใช้เสียง s ส่วน close ที่แปลว่าปิด (noun กับ verb) ใช้เสียง z
- douse louse mouse ใช้เสียง s แต่ rouse spouse ใช้เสียง z
- precise กับ concise ใช้เสียง s ส่วน incise exercise ฯลฯ ใช้เสียง z (ข้อสังเกตุ: precise กับ concise ไม่มีรูป verb)
- garrison ใช้เสียง s แต่ visage ใช้เสียง z
ตัวอย่าง: เสียงสระเหมือนกัน ทางซ้ายเสียง s ทางขวาเสียง z
place - plays
ice - eyes
miss - Ms.
price - prize
hence - hens
dense - dens
rice - rise
race - raise
race - rays
race - raze
loose - lose
goose - goos
hiss - his
use(noun) - use(verb)
face - phase
bus - buzz
ass - as
lense - lens
(lense กับ lens ความหมายเหมือนกันนะ)
decease - disease
(s ใน decease ใช้เสียง s ส่วน s ทั้งสองที่ใน disease ใช้เสียง z)
close(adj) - close(v)
close(adj) - clothes(n)
ice - eyes
miss - Ms.
price - prize
hence - hens
dense - dens
rice - rise
race - raise
race - rays
race - raze
loose - lose
goose - goos
hiss - his
use(noun) - use(verb)
face - phase
bus - buzz
ass - as
lense - lens
(lense กับ lens ความหมายเหมือนกันนะ)
decease - disease
(s ใน decease ใช้เสียง s ส่วน s ทั้งสองที่ใน disease ใช้เสียง z)
close(adj) - close(v)
close(adj) - clothes(n)
ตัวอย่างเปรียบเทียบตัวสะกด ทางซ้ายเสียง s ทางขวาเสียง z (เสียงอื่น ๆ ก็ต่างกัน):
racist - racism
purpose - propose
(purpose สระเสียงสั้น propose สระเสียงยาว)
promise - compromise
(promise สระเสียงสั้น compromise สระเสียงยาว)
analysis - analyses
(analyses เป็นรูปพหูพจน์ ... s ตัวแรกเป็นเสียง s ในทั้งสองคำนะ)
crease - ease
its - is
this - his
intense - intends
laps - labs
motes - modes
docks - dogs
strifes - strives
purpose - propose
(purpose สระเสียงสั้น propose สระเสียงยาว)
promise - compromise
(promise สระเสียงสั้น compromise สระเสียงยาว)
analysis - analyses
(analyses เป็นรูปพหูพจน์ ... s ตัวแรกเป็นเสียง s ในทั้งสองคำนะ)
crease - ease
its - is
this - his
intense - intends
laps - labs
motes - modes
docks - dogs
strifes - strives
Wednesday, September 27, 2006
เรื่อง Stanford
จะบอกว่า ถ้าจะดูเรื่องเกี่ยวกะชีวิตนู้บสแตนฟอร์ดเนี่ย ให้ไปดูที่ Another Tunoblog แทน ขี้เกียจ update สองที่หนะ
Thursday, September 21, 2006
เด็กบ้านนอก - นู้บ
เผื่อคนที่ไม่รู้ ตอนนี้อยู่ที่ 119 Quillen Court, #500, Stanford CA 94305 นะ วันจันทร์จะเปิดเทอมแล้ว
ไปอยู่ในที่ใหม่ มันก็มีอะไรต้องศึกษาใหม่เยอะนะ ... สถานที่ก็ใหญ่ เดินทางก็ลำบาก ถึงจะฟรีก็เหอะ รู้สึกมันบ้านนอกบ้านนอกไงก็ไม่รู้
ไม่ค่อยมีเวลาเขียนเท่าไหร่เลย ช่วงนี้มีงานมีเหตุการณ์มากมาย ... ไว้มีเวลาแล้วจะมาเขียนอีกเยอะ ๆ ละกัน
ป.ล. เพิ่งรู้ว่า IE มันไม่ยอมให้เขียนสระอาติดกันหลาย ๆ ตัวใน Edit Box อะ แย่จัง
Thursday, August 10, 2006
Siam Paragon
คำอ่าน "Siam Paragon" เป็นภาษาไทยเนี่ย ...
- สยามภาระก้น
- สยามปลาร้าก้อน (เพี้ยนนิดหน่อย)
Sunday, July 02, 2006
Programming: Space-Time Relation
ขอเริ่มต้น post ของวันนี้ด้วยการขอโทษก่อนละกัน วันนี้ (จริง ๆ เมื่อวานด้วย) ไม่ได้ไปเยี่ยมบัณฑิตจุฬา ฯ ที่ไปซ้อมรับปริญญา เพราะมีเหตุการณ์สำคัญเกิดขึ้นที่บ้าน ที่คนทั่ว ๆ ไปคงเรียกว่าปัญหาครอบครัวหนะ
แล้วก็ ... เตือนกันอีกครั้งนะ ... ถ้าจะดู post เก่า ๆ ให้มันเป็นลำดับดี ๆ ไปดูที่นี่
มันจะมี link มาที่หน้าของแต่ละ post ใน Tunoblog อันนี้
โปรโมตเสร็จ ก็ขอเข้าเรื่องละกัน คราวนี้จะพูดถึงความสัมพันธ์ระหว่าง ความเร็วของ algorithm กับเนื้อที่ memory ที่จะต้องใช้
สำหรับปัญหาปัญหานึง เราอาจจะมีวิธีแก้หลาย ๆ แบบ ซึ่งสำหรับนักเขียนโปรแกรมเนี่ย เค้ามักถามกันว่า "บิ๊กโอ (Big-O = O ใหญ่น่ะแหละ) เท่าไหร่?"
ใครที่ยังไม่รู้จัก O ตัวนี้ ก็ขอพูดคร่าว ๆ ละกัน
O(g) = { f | f(x) เพิ่มไม่เร็วกว่า g(x) เมื่อ x มีค่ามาก ๆ }
จริง ๆ นิยามแบบชัด ๆ มันก็มีอยู่อะนะ แต่ขี้เกียจยกมา ไปดูเอาเองจาก Wikipedia ละกัน :P
มาต่อกันเรื่องหลัก คราวนี้มาสนใจเรื่อง Space-Time ดีกว่า ...
ทฤษฎีสัมพัทธภาพ
ม่ายช่ายและ :P ... จะพูดถึง Big-O ของเวลา กับ เนื้อที่ memory ที่ algorithm ใช้ตะหาก
Sorting Algorithm
ปัญหาการเรียงข้อมูลเนี่ย เป็นปัญหาสุดคลาสสิก ที่น่าเอามาพูดถึงที่สุด วิธีการเรียงที่นิยมสอนกัน มักจะมีอยู่เท่านี้ (ขาดเกินบ้างนิดหน่อย)
- Selection Sort - ใช้เวลา O(n2) เมื่อมีข้อมูล n ตัว
- Bubble Sort - ใช้เวลา O(n2)
- Insertion Sort - ใช้เวลา O(n2)
- Shell Sort - ใช้เวลา O(n1.5) (จริง ๆ มี O(n log2n) นะ ดูที่นี่)
- Merge Sort - ใช้เวลา O(n log n)
- Quick Sort - ใช้เวลา O(n log n) (เฉลี่ย)
- Heap Sort - ใช้เวลา O(n log n)
- Bucket Sort - ใช้เวลา O(m + n)
- Radix Sort - ใช้เวลา O(n log m)
หนังสือทั่ว ๆ ไป มักจะไม่พูดถึงขนาดของ memory ที่ต้องใช้ เพราะว่า ไม่มีิอันไหนใช้เกิน O(n) ซึ่งเป็นขนาดของ input แต่เราจะลองมองดูซักนิดนะ ว่ามันเป็นยังไง
- Selection Sort - ใช้เนื้อที่เพิ่ม O(1)
- Bubble Sort - ใช้เนื้อที่เพิ่ม O(1)
- Insertion Sort - ใช้เนื้อที่เพิ่ม O(1)
- Shell Sort - ใช้เนื้อที่เพิ่ม O(1)
- Merge Sort - ใช้เนื้อที่เพิ่ม O(n)
- Quick Sort - ใช้เนื้อที่เพิ่ม O(log n) (เฉลี่ย)
- Heap Sort - ใช้เนื้อที่เพิ่ม O(1)
- Bucket Sort - ใช้เนื้อที่เพิ่ม O(m)
- Radix Sort - ใช้เนื้อที่เพิ่ม O(1)
- Selection Sort - ลูป 2 ชั้น และตัวแปรพักข้อมูลสำหรับการสลับ
- Bubble Sort - ลูป 2 ชั้น และตัวแปรพักข้อมูลสำหรับการสลับ
- Insertion Sort - ลูป 2 ชั้น และตัวแปรพักข้อมูลสำหรับการแทรก
- Shell Sort (กรณีเวลา O(n log2n)) - ลูป 3 ชั้น ตัวแปรสำหรับสร้างลำดับ 2 ตัว และตัวแปรพักข้อมูลสำหรับการสลับ หรือ แทรก
- Merge Sort - Recursive 2 ครั้ง ลูป 1 ชั้นที่มีตัวนับ 2 ตัว กับ array พักข้อมูลความยาว n และลูปคัดลอกค่าจาก array พักข้อมูล
- Quick Sort - ลูป 1 ชั้นที่มีตัวนับ 2 ตัว ตัวแปรพักข้อมูลสำหรับการสลับ และ Recursive 2 ครั้ง
- Heap Sort - ลูป 2 ชั้น 2 ลูป และตัวแปรพักข้อมูลสำหรับการแทรก
- Bucket Sort - ลูปกำหนดค่าเริ่มต้น (ใช้เวลา O(m)) ลูปรับ input และลูปแสดง output (ใช้เวลา O(n))
- Radix Sort (ฐาน 2) - ลูป 2 ชั้น ชั้นนอกทำซ้ำ log2m ครั้ง ชั้นในมีตัวนับ 2 ตัว
Dynamic Programming - Fibonacci Function
อันนี้ คิดว่า หลาย ๆ คนคงคุ้นเคยและรู้อยู่แล้ว หน้าตามันก็ประมาณนี้ (ภาษา C ละกัน)
int fib(int n) { return n <= 1 ? 1 : fib(n - 1) + fib(n - 2); }
จะเห็นว่า code สั้นมาก ดังนั้น จากหลักของเรา พอจะเดาได้ว่า น่าจะมีวิธีทำให้มันทำงานเร็วกว่านี้ แต่ code ยาวกว่านี้ หรือมีตัวแปรเพิ่ม
ลองดูก่อน ว่า เขียนโปรแกรมแบบนี้ ใช้เวลาทำงานเท่าไหร่ ... คำตอบค่อนข้างง่ายนะ เวลาก็คือ O(fib(n)) น่ะแหละ (ว่าไปก็คือ O(αn) เมื่อ α = golden ratio น่ะแหละ)
มันกินเวลาน่าดูเลยนะเนี่ย ลองพยายามทำให้มันเร็วขึ้นสิ ... วิธีง่าย ๆ ก็คือ กำหนดตัวแปรเพิ่มเป็น array ความยาว n แล้วก็คิดค่าไล่ตั้งแต่ f(0) ถึง f(n) ไง หยั่งงี้ f(...) ตัวที่เคยคิดแล้ว ก็ไม่ต้องคิดซ้ำ
int fib(int n) { return a[n] > 0 ? a[n] : a[n] = fib(n - 1) + fib(n - 2); }
แล้วกำหนดค่าเริ่มต้นให้ a[0] = 1, a[1] = 1 และ a[อื่น ๆ] = -1
จริง ๆ มันประหยัดเนื้อที่ได้อีกนะ แต่คราวนี้โปรแกรมจะซับซ้อนละ ...
int fib(int n)
{
int f, last1, last2;
if (n <= 1) return 1;
last1 = 1;
last2 = 1;
for (--n; n > 0; --n)
{
f = last1 + last2;
last2 = last1;
last1 = f;
}
return f;
}
จะเห็นว่า เหลือตัวแปรแค่ 3 ตัว (คือ memory O(1)) แลกกับ code ที่ยาวขึ้นอีกนิดนึง
จริง ๆ ยังทำให้มันเร็วกว่านี้ได้อีกแหละ แต่คราวนี้ code จะยาวขึ้นเยอะเลย แล้วจะเร็วขึ้นเฉพาะเมื่อ n เยอะมาก ๆ ๆ ๆ ๆ เท่านั้น
เอาเป็นว่า หยุดแค่นี้ก่อนดีกว่า
Friday, June 30, 2006
Programming: Stack and Recursion
ไม่ยอมเขียนมาซะนาน ขอกลับมาทำบ้างซักครั้งละกัน ... คิดถึงจัง ความรู้สึกนี้ :D
คราวนี้จะพูดถึงเรื่องการเขียนโปรแกรมซักหน่อยนะ คาดว่าจะเป็นประโยชน์กับ programmer รุ่นเด็ก ๆ บ้างนะ
Stack and Recursion
หลาย ๆ คนคงรู้อยู่แล้วว่าทั้งสองอย่างนี้มันคืออะไร และมันเกี่ยวกันยังไง ... ใครไม่รู้อ่านต่อละกัน :P
Stack
- กลุ่มข้อมูลคล้าย ๆ หลอด CD ที่ใช้เสียบแผ่นหลาย ๆ แผ่นเข้าด้วยกัน
- คุณสมบัติก็คือ จะใส่เพิ่มหรือจะหยิบออก จะต้องทำจากข้างบน
- การทำซ้ำ ๆ ที่เกิดจากการฟังก์ชันที่เรียกกันเป็นวง เช่น f เรียก g แล้ว g เรียก h แล้ว h เรียก f ไปเรื่อย ๆ
- สิ่งที่จำเป็นในการเขียนโปรแกรมแบบ Recursive ก็คือ จะต้องมีเงื่อนไขการหยุด
จริง ๆ อยากให้ไปอ่านเรื่องที่ทำ Virtual Machine จัง แต่มันคงจะยาวไปเนอะ ... สรุปเลยละกัน :P ง่าย ๆ ก็คือ ... ทุกครั้งที่เรียกฟังก์ชัน เราต้องเพิ่มข้อมูลบางอย่างใน Stack ของ CPU แล้วพอฟังก์ชันทำงานเสร็จ เราก็จะเอาของพวกนั้นออก
แปลว่า ... ที่เราสามารถเขียนโปรแกรมแบบ recursive ได้เนี่ย ก็เพราะว่า CPU มันมี Stack อยู่
และก็แปลว่า ... เราสามารถสร้าง Stack ขึ้นเอง แล้วก็ไม่ต้องไปรบกวน Stack ของ CPU ได้เหมือนกัน
ลองดูตัวอย่างเลยละกัน สมมติว่าเรามีฟังก์ชันที่เขียนแบบ recursive ตัวนึง
function f(x)
begin
if x <= 0 then return 0;
else return 2x - 1 + f(x - 1);
end
ถ้าเรามี Stack เราจะเขียนแบบไม่ recursive ได้เป็น
function f(x)
begin
push x onto Stack;
push "not done" onto Stack;
while Stack is not empty
do
assign op ← Top of Stack;
Remove Top of Stack;
assign x ← Top of Stack;
Remove Top of Stack;
if op = "not done" then
begin
push x onto Stack;
push "done" onto Stack;
if x <= 0 then do nothing;
else
begin
push x - 1 onto Stack;
push "not done" onto Stack;
end
end
else if op = "done" then
begin
if x <= 0 then assign ReturnValue ← 0;
else assign ReturnValue ← 2x - 1 + ReturnValue;
end
end while
return ReturnValue;
end
จะเห็นว่า มันยาวขึ้นมาก -_-'' จริง ๆ จะทำให้สั้นกว่านี้ก็ได้อีกเยอะหนะนะ แต่นี่เป็นตัวอย่างการแปลงแบบตรงไปตรงมา ฟังก์ชันอะไรเราก็แปลงแบบนี้ได้
แอบอัพเดท
โทษทีที่ยังไม่ได้เอารูปตอนไปยุโรปมาลงให้ จะเอามาให้ดูจริง ๆ แหละ แต่รอก่อนนะ ตอนนี้ขอแอบกลับไปเขียนเรื่องบ้า ๆ ต่อก่อน
Tuesday, June 27, 2006
ฟันคุด
ไปผ่าฟันคุดมาเมื่อวันศุกร์ที่แล้วหนะ . . . ผ่าข้างล่างสอง ถอนข้างบนสอง
ก่อนหน้านี้ มีคนขู่ไว้เพียบเลย - -'' พอทำเอง มันก็ไม่ได้น่ากลัวขนาดนั้นซะหน่อย
พอเจอหมอ หมอเค้าก็คุยก่อนนะ เค้าบอกว่า ฟันมันเอียงมาก (ประมาณ 70 องศา จากที่เห็นในฟิล์ม) เอียงเหมือนจะไปดันซี่ข้าง ๆ ด้วย ถ้าจะเอาออก จะต้องทำให้มันเป็นชิ้นเล็กชิ้นน้อยก่อน วิธีทำก็คือ ค่อย ๆ กรอเนื้อฟันออก จนมันบางลง ก็ออกแรกบีบให้มันแตก ... ฟังดูน่ากลัวมะ
พอถึงเวลาจริง ที่เจ็บที่สุดก็เห็นจะเป็นเข็มฉีดยาชานี่แหละ (มันก็ไม่ได้เจ็บมากหรอก บริจาคเลือดยังเจ็บกว่าอีก)
เริ่มแรก เค้าฉีดยาชาเสร็จแล้วก็รอแป๊บนึง แล้วก็เอาคีมมางัดแงะดึงฟันข้างบนออก เดี๋ยวเดียวเสร็จเลย รู้สึกว่าอะไร ๆ มันก็เร็วกว่าที่คิดนะ
แต่อีกสองซี่ที่ต้องทำให้เป็นชิ้น ๆ เนี่ย ใช้เวลานานกว่าที่คิดแฮะ
ช่วงที่รู้สึกเสียว ๆ ก็มีนะ ช่วงแรกคือ ตอนที่หมอกำลังขัดเนื้อฟันข้างขวาออกเนี่ย เค้าออกแรงเยอะมาก จนรู้สึกว่ามันตึงที่ข้างนอกเลย
อีกช่วงนึงก็ ... จริง ๆ ไม่ได้รู้สึกเจ็บหรือเสียวฟันอะนะ เป็นความเสียวทางความคิดหนะ คือประมาณว่า ผู้ช่วยหมอเค้าไม่ใส่แว่นแล้วมองเห็นไหมไม่ชัด (สีมันคล้าย ๆ น้ำลาย) หมอก็ต่อว่า ว่าถ้ามองไม่ชัด คราวหน้าต้องใส่แว่นมานะ ไม่งั้นไม่ต้องมาช่วย - -'' เสียวมั้ยหละ
แล้วหลังจากนั้นแป๊บเดียว หมอก็บอกอีกว่า ไหมเนี่ย ผู้ช่วยดึงไม่แน่น ... แล้วหมอก็ทำอะไรอีกก็ดูไม่รู้เรื่อง อาจจะเอาออก เย็บใหม่ก็ได้ (ยังไงตอนนี้ก็ดูไม่ออกแล้ว)
พอทำเสร็จ ก็ไม่รู้สึกเจ็บเลยนะ แต่มันเมื่อยนิด ๆ เพราะต้องกัดสำลีไว้ตั้งหลายชั่วโมง แล้วก็ต้องคอยเอาน้ำแข็งประคบด้วย
วันแรกหลังจากทำ ก็ไม่เจ็บนะ แค่รำคาญว่าเวลากินอะไร เศษมันจะติด ๆ แล้วเอาออกไม่ได้ แล้วก็เจ็บนิดหน่อยเวลากลืน เพราะว่ามีแผลที่ลิ้นนิดนึง
วันที่สองก็ รู้สึกเหมือนวันแรก ... ไม่ค่อยรู้สึกว่ามันจะดีขึ้นแฮะ - -''
วันที่สามเนี่ย เริ่มรู้สึกดีขึ้นละ แต่ก็ยังกินอะไรที่ต้องเคี้ยวไม่ได้หนะ ยังกินแต่ไข่ตุ๋น มันฝรั่งบด แล้วก็โจ๊ก
วันนี้วันที่สี่แล้ว ... ทำไมมันรู้สึกเจ็บ ๆ อะ T_T ... ความเจ็บมันมีการหน่วงเวลาด้วยแฮะ ...
Sunday, May 21, 2006
กลับมาละ
หลังจากวันจันทร์ที่แปดแล้ว ก็หาเน็ตไม่ได้เลยอ่า เอาเป็นว่า สรุปการไปเยือนเมืองนอกเอาทีเดียวเลยละกัน ... อ้อ ยังไม่ได้เอาภาพจากกล้องมาลงหนะ อ่านแห้ง ๆ ไปก่อนละกัน :P
ก็ ... ต่อจากตอนที่แล้ว ก็ไปโรงงานกะโรงแรม สลับกันไปเรื่อย ๆ หละ จนวันที่สิบสอง ก็ขึ้นเครื่องบินไป Venezia จากสนามบิน Marco Polo ก็มีคนมารับไปโรงแรมแถว ๆ Padova ชื่อว่า Ibis
ที่โรงแรมนี้ ลิฟท์ก็แปลกไปอีกแบบ คือมันไม่มีปุ่มเปิดประตู (โรงแรมที่แล้วไม่มีปุ่มปิด)
สภาพส่วนใหญ่ในโรงแรมนี้ ดีกว่าโรงแรมที่แล้วนะ แต่ว่า ... มันไม่มีเน็ต T_T
เย็นวันศุกร์ ได้ไปแวะซุปเปอร์มาร์เก็ตใกล้ ๆ โรงแรมด้วยหละ รู้สึกว่าของมันแพงจัง ... เดินอยู่ในนั้นพอประมาณ ก็ซื้อน้ำเปล่ามา กับขนมนิด ๆ หน่อย ๆ
พอวันเสาร์ ก็ไปเดินเล่นในเมือง Padova มีร้านเสื้อผ้า เครื่องแต่งกาย เยอะมาก แล้วก็มีตลาดนัดด้วย ดูคล้าย ๆ เมืองไทยเลยแต่ว่าบรรยากาศมันดีจัง ติดอยู่ตรงที่น้ำดื่มมันแพง ... เดิน ๆ แล้วหิวน้ำ ก็ไม่ค่อยอยากซื้อ
ตอนกลางวันกินข้าวที่ Pizzeria อะไรก็ไม่รู้ จำชื่อไม่ได้ สั่งพิซซ่ากินกับพ่อคนละถาด (ราคาถาดละแปดยูโร) ถาดมันใหญ่กว่าที่คิดแฮะ แต่ก็กินจนหมดได้หละน่า!
หลังจากนั้นก็เดิน ๆ ไปเรื่อย ๆ ไม่ได้ซื้ออะไรเลย :( ก็มันไม่มีอะไรน่าซื้อหนิ ): ขึ้นรถเมล์กลับโรงแรม แล้วก็กินข้าวเย็นที่โรงแรม ... จบวัน
วันอาทิตย์ ทุกอย่างปิดหมด รถเมล์ไม่วิ่ง ถ้าจะไปไหน ต้องเรียกแท็กซี่ราคาสุดโหด ก็เลยดิ้น ๆ อยู่แค่ในโรงแรม T_T นอนแต่หัวค่ำ เตรียมไปทำงานเช้าวันจันทร์
ประมาณแปดโมงครึ่ง (เช้า) วันจันทร์ ก็ไปที่โรงงานอีกแห่งนึง คุย ๆ กะเค้าถึงซักสิบโมงสิบห้านาทีโดยประมาณ ก็ต้องไปโรงงานอีกที่นึง ที่นี้อยู่ใน Belluno ซึ่งก็ไกลพอควรเลย นั่งรถไปประมาณสี่สิบห้านาที ยังอยู่ระหว่างทางไปโรงงาน ก็เห็นภูเขาอยู่สองข้างถนน มองไปไกล ๆ หน่อยจะเห็นยอดเขาสีขาว ๆ ปกคลุมด้วยหมอกและหิมะ ... ดูดีจัง
นั่งต่อไปอีกประมาณครึ่งชั่วโมง คราวนี้ทางขวามือไม่มีภูเขาแล้ว แต่เป็นเมืองแทน มองเมืองจากตรงนี้ก็สวยดีแฮะ
แล้วอีกประมาณสิบห้านาที ก็ถึงที่หมาย ... โรงงานอีกแห่ง
คุย ๆ กะเค้า ถึงประมาณบ่ายสาม ก็ต้องกลับ Venezia แล้ว เพราะว่าจะต้องขึ้นเครื่องบินกลับไป Roma เพื่อจะไปต่อเที่ยวบินไปยัง Frankfurt
กลับไปถึง Roma ก็ไม่มีโรงแรมพักในเมืองอีก ต้องออกจากเมือง ไปพักโรงแรมใน Pomezia (คนละโรงแรมกับครั้งแรกนะ) ปุ่มในลิฟท์ของโรงแรมนี้เนี่ย ... คราวนี้ มันมีเลข 0 ถึง 9 เรียงเหมือนเครื่องคิดเลขเลย แต่ตึกมันมีไม่ถึง 9 ชั้นอะ ...
นอน ตื่น วันอังคารละ คราวนี้ บินจากสนามบิน Fiumicino ไปสนามบิน Frankfurt
เห็นภาษาเยอรมันแล้ว รู้สึกว่าอ่านยากกว่าอิตาลีเยอะเลย (คือ เดาความหมายไม่ค่อยได้เลย) คำที่รู้ก็เลยมีน้อยกว่า ... คือ ได้ประมาณเนี้ย
eingang = ทางเข้า
ausgang = ทางออก
toiletten = ส้วม
fahrkarten = ตั๋ว
bahnhof = สถานีรถราง/รถไฟ
haupt = หลัก (head, main)
platz = place
markt = market
ausgang = ทางออก
toiletten = ส้วม
fahrkarten = ตั๋ว
bahnhof = สถานีรถราง/รถไฟ
haupt = หลัก (head, main)
platz = place
markt = market
โรงแรมที่พัก ชื่อว่า Winter's Eurotel Boardinghouse อยู่ในเมือง Offenbach ที่ไม่ได้พักใน Frankfurt ก็เพราะว่าจองโรงแรมใน Frankfurt ไม่ทัน มันเต็มหมดเลย (หรือไม่ก็แพงสุด ๆ) ที่นี่ มีอินเทอร์เน็ตแบบไร้สายนะ แต่ว่า ราคายี่สิบสี่ยูโรครึ่ง ต่อ ยี่สิบสี่ชั่วโมง เลยไม่เอา
วันพุธ ตื่นเช้าหน่อย ไปดูงาน Achema 2006 ละ ... ในนี้ ถ่ายรูปไม่ค่อยได้หนะ เลยไม่มีรูปมาโชว์เยอะเท่าไหร่
งานนี้ใหญ่มากเลย สถานที่จัดงานเรียกว่า Messe Frankfurt มี Hall ทั้งหมดสิบ Hall แต่ละ Hall มีขนาดเท่าศูนย์ ฯ สิริกิติ์เลยมั้ง แล้วยังให้เดินได้ Hall ละหลาย ๆ ชั้นด้วย ... เดินยังไงจะครบเนี่ย
ค่าบัตรเข้างาน เค้าคิดคนละยี่สิบสามยูโร งานเปิดวันละเก้าชั่วโมง คือตั้งแต่เก้าโมงเช้า ถึงหกโมงเย็น ดังนั้น ค่าเข้าชมงาน ถ้าอยู่ตลอดเก้าชั่วโมง ก็ตกเฉลี่ยชั่วโมงละ 2.56 ยูโร (ประมาณนาทีละสองบาท)
ของกินในงานเนี่ย แย่จัง ... มีแค่ขนมปังกะไส้กรอก แล้วก็ไอติมเนสท์เล่ ราคาแต่ละอย่าง ไม่สมกับปริมาณเลย ไส้กรอกหนึ่งเส้นกับขนมปังห่วย ๆ หนึ่งก้อน ราคาสองยูโรครึ่ง ไอตินเนสท์เล่สองลูกเล็ก ๆ (เน้นว่าเล็ก ๆ) บนโคนหนึ่งอัน ก็ราคาสองยูโรครึ่ง ส่วนน้ำเปล่ากับน้ำอัดลม ราคาเท่ากันคือแก้วละสองยูโร ตอนแรกต้องมัดจำค่าแก้วใบละครึ่งยูโรด้วย (เอาแก้วไปคืน จะได้เงินคืนมา)
จริง ๆ วัฒนธรรมการมัดจำภาชนะเนี่ย มันก็มีหลายประเทศแล้วแหละ ... น่าแปลกเหมือนกัน ที่อิตาลีเค้าไม่มีแบบนี้
ตอนเย็น พองานปิด ก็เดินไปที่ Frankfurt Hauptbahnhof แล้วขึ้นรถไฟสาย S9 ไปที่ Offenbach Marktplatz กะจะหาของกิน ที่ไหนได้ เค้าปิดกันเกือบหมดแล้ว ... เหลือ KFC เปิดอยู่ ไปกินก็ได้ - -''
วันพฤหัสก็ ไปดูงานอีกวัน ไม่มีไรมากหรอก ก็อยู่ในงานทั้งวัน ตอนเย็นก็ไปหาของกิน แต่คราวนี้ ไม่ได้ไป KFC ละ เพราะว่าออกจากงานก่อนเวลาปิดนิดนึง ร้านอาหารอื่นเค้ายังไม่ปิด วันนี้ไปกินขาหมูเยอรมันที่ร้าน ... ลืมชื่อไปแล้ว :P
วันศุกร์ ไปเที่ยวละ คราวนี้ เริ่มเดินจาก Frankfurt Hauptbahnhof ไปยัง Hauptwache แถวนี้ร้านขายของเยอะมากเลย มี Department Store แปดชั้นด้วย ... ของที่ขายก็เหมือน ๆ ร้านในกรุงเทพ ฯ นี่แหละ ... ที่ต่างจากห้างของเมืองเราก็มีบันไดเลื่อนนี่แหละ ... ชั้นนึงมันต่อกับบันไดเลื่อนแปดอันหนะ สะดวกดี ... (ถ้าไม่เข้าใจ รอดูภาพละกัน)
อยากจะซื้อของกลับไปฝากหลาย ๆ อย่างนะ แต่มันมีแต่ช็อกโกแล็ตอะ - -''
วันเสาร์แล้ว วันนี้จะกลับละ แต่ขอไปซื้อของฝากอีกนิดนึงก่อน ... เครื่องบินเค้าเรียกเข้าตอนบ่ายสองสิบห้านาที บังเอิญว่าไปถึงสนามบินแต่เช้า ก็เลยมีเวลาเดินหาของนานหน่อย ... แย่จัง มีเวลาเยอะ แต่ของมันดันมีน้อย ... ไป ๆ มา ๆ ก็มีแต่ช็อกโกแล็ตอะ
บ่ายสามนิด ๆ เครื่องบินก็เริ่มปลดเปลื้อง ... บนเครื่องบินคราวนี้ ฉายหนังสองเรื่อง เรื่องแรกคือ Prime อีกเรื่องคือ King Kong
... หมดละ ถึงกรุงเทพ ฯ ซะที!
Monday, May 08, 2006
วันนี้ก็ยาวอีกแล้ว
ตื่นตอนเช้า กินอาหารเช้า แต่งตัว ... พอถึงเก้าโมงก็มีคนมารับไปโรงงาน
ถ่ายรูปโรงงานเค้าได้ซักสิบกว่า ๆ รูป กล้องดันแบตหมด - -'' ... ช่างมัน พรุ่งนี้ค่อยไปถ่ายใหม่ละกัน (จริง ๆ แบตมันก็อยู่ใกล้ ๆ แหละ แต่ไม่มีโอกาสไปหยิบ)
ในโรงงานเค้ามีตู้ขายกาแฟร้อนด้วย หยอดได้แต่เหรียญนะ ... ใกล้ ๆ ตู้ก็มีป้ายห้ามสูบบุหรี่ (ถ้าสูบ จะถูกปรับตั้งแต่ 28.5 ถึง 285 ยูโร) แต่คนงานเค้ามาสูบตรงนี้เพียบเลย ... ก็มันสูบกันทุกคนหนิเนอะ
พอบ่ายโมง เค้าก็พาไปกินข้าวกลางวัน เป็นโรงอาหารของโรงงานแหละ แต่อาหารก็พอใช้ได้นะ ... (ดีกว่าข้าวกลางวันของสาธิตจุฬาฯ ฝ่ายประถม แน่ ๆ)
ประมาณบ่ายสอง ก็กลับไปฟังเค้าบรรยายเรื่องเครื่องมือ เอา drawing มาให้ดูเพียบเลย ... เริ่มรู้สึกว่าตัวเองกะเหรี่ยงแฮะ ไม่รู้จักเครื่องหมายเค้าเลย (แต่พอฟัง ๆ แล้วก็เริ่มจะเข้าใจบ้างหละ)
ก่อนจะไปกินข้าวเย็น เรื่องสุดท้ายที่เค้าบรรยายก็คือ Plasma Sterilizer ซึ่งผู้ผลิตรายที่ดังที่สุดคือ Johnson & Johnson ทำอยู่เจ้าเดียวมาสิบปีแล้ว เพิ่งจะมีคนอื่นเริ่มทำก็ปีที่แล้วเนี่ยแหละ การทำงานของมันก็เข้าใจไม่ยากนะ แต่ทำยากจัง เค้าบอกว่า ต้องใช้ High Vacuum Pump เพื่อทำความดันภายใน chamber ให้ได้ต่ำถึง 0.01 millibar สัมบูรณ์ จากนั้นก็พยายามทำให้อิเล็กตรอน หลุดออกจากโมเลกุลของอากาศที่ยังเหลืออยู่ โมเลกุลมันก็จะไวต่อสนามไฟฟ้าเพราะมันมีประจุ ส่วนอิเล็กตรอนที่หลุดออกไป มันก็ไวเหมือนกัน พอของพวกนี้วิ่งไปชนกับสารอินทรีย์ พันธะมันก็จะแตกออกง่าย ๆ เค้าก็เลยใช้วิธีนี้ฆ่าเชื้อ ... เพื่อจะทำให้อิเล็กตรอนมันหลุดง่าย ๆ เค้าก็ใส่ก๊าซที่มีความเสถียรต่ำ เพิ่มลงไปด้วย (อันนี้เค้าใช้ H2O2)
ข้อดีของวิธีนี้ก็คือ ใช้อุณหภูมิต่ำ คือ ประมาณ 40 - 55 °C เท่านั้น เลยใช้กับพลาสติกหรือวัสดุไม่ทนความร้อนได้ แต่ข้อเสียก็คือ ของที่ใส่เข้าไปต้องแห้งจัด ๆ
ความรู้ที่ได้เพิ่มตรงนี้มีสองเรื่อง คือ
- เหตุผลที่ต้องให้ของของเรา แห้งจัด ๆ ก็เพราะว่า ที่ความดัน 0.01 mbar สัมบูรณ์เนี่ย จุดเดือดของน้ำจะต่ำมาก (เกือบ 0°C) น้ำทั้งหมดจะกลายเป็นไอ ทำให้ปริมาณก๊าซใน chamber เพิ่มขึ้น ซึ่งก็แปลว่า ความดันจะเพิ่มด้วย มันก็จะไม่ใช่ 0.01 mbar แล้ว ตัว vacuum pump ต้องดูดเอาพวกนี้ออกให้หมดด้วย กระบวนการแบบนี้จะกินแรง pump มาก ๆ บางครั้งเครื่องอาจจะหยุดทำงานไปเลย แล้วแจ้งเตือนว่าความชื้นสูงเกินไป
- สถานะของก๊าซที่มีประจุเนี่ย เรียกว่า plasma (กะเหรี่ยงมั้ยเนี่ย ไม่รู้มาก่อน :P)
ที่ร้านอาหาร เค้าก็สอนภาษาอิตาลีให้นิด ๆ หน่อย ๆ เอาสนุก ส่วนใหญ่คือ จะแปลเมนูภาษาอิตาลีให้ฟัง (ร้านนี้ไม่มีเมนูภาษาอังกฤษ) จำได้นิดเดียวเอง ประมาณเนี้ย ...
acqua = water
antipasto = appetizer
zucchero = sugar
salmone = salmon
melone = melon
limone = lemon
fritto = fried
misto = mixed
mare = sea
pesce = fish
pescatore = fisherman
calamari = squid(s)
patata = potato
funghi = mushroom(s)
antipasto = appetizer
zucchero = sugar
salmone = salmon
melone = melon
limone = lemon
fritto = fried
misto = mixed
mare = sea
pesce = fish
pescatore = fisherman
calamari = squid(s)
patata = potato
funghi = mushroom(s)
อ้อ ... แล้วก็ calcium เนี่ย เค้าอ่านว่า "คัลชุ่ม" แหละ
กินเสร็จก็กลับโรงแรมเลย ... ตอนนี้ก็ เลยเที่ยงคืนแล้วอ่า ... ไปนอนละ
Sunday, May 07, 2006
วันนี้ยาวจัง
กะจะเอารูปมาให้ดูด้วย แต่ว่าลืมเอาสายต่อกล้องมา เลยเอาลงเครื่องคอมพ์ไม่ได้ T_T เล่าให้ฟังเป็นตัวอักษรอย่างเดียวก่อนละกัน
ประมาณเที่ยงคืนครึ่ง วันนี้ ขึ้นเครื่องบิน สายการบินไทย ประตูยี่สิบสี่ ปลายทาง กรุงโรมนะครับ นั่งรอจนเที่ยงคืนห้าสิบห้า เครื่องบินก็เริ่มเปลื้องผ้า (Take Off)
ตอนแรก บนจอทีวี เปิดซีรีส์ซิทคอมเรื่อง ... จำชื่อเรื่องไม่ได้อะ ... ก็ฮาใช้ได้ รายการต่อจากนั้นก็เป็น ดนตรีคลาสสิก ไม่สิ ดนตรีบาโรค มาพร้อมกับอาหารมื้อตีหนึ่งกว่า ๆ พอกินกันเสร็จ ผู้คนก็เริ่มหลับกัน (สงสัยเพราะเพลงน่ะแหละ) ... เรายังไม่อยากนอน ก็เลยนั่งวาดรูปเล่น (รูปเรขาคณิตหนะ กำลังคิดเรื่องที่ทำวิจัยอยู่ ... คิดไปคิดมา ได้ความว่า มันยากกว่าที่เคยคิดแฮะ) ผ่านไปประมาณชั่วโมงนึง เริ่มง่วง ๆ เลยนอนมั่ง
ตื่นมา เค้าเปิด Narnia ให้ดูด้วย ... ดูแล้วก็เลยรู้ ว่าทำไมคนถึงด่ากันจัง ... ดูจบ กินข้าว รออีกแป๊บนึงก็หกโมงเช้าสามสิบห้านาที ถึงเวลาเครื่องบินแตะพื้นกรุงโรมละ
ตรงที่ตรวจหนังสือเดินทางเนี่ย คนแน่นมากกกก ... กว่าจะออกจากสนามบินได้ ประมาณชั่วโมงนึงแหนะ ... จะบอกว่า ห้องน้ำในสนามบิน Fiumicino เนี่ย แย่กว่าดอนเมืองพอควรเลย
ออกมา ก็มีคนขับรถมารับ ... รู้สึกไม่ค่อยคุ้นเคยกับรถชิดขวาเลยแฮะ ... นั่งรถประมาณครึ่งชั่วโมงก็ถึงโรงแรม Hotel Centrale ใน Pomezia
เนื่องจาก Pomezia เป็นย่านอุตสาหกรรม ก็เลยไม่มีที่ท่องเที่ยวให้ดูเลย ... แต่ที่แย่กว่านั้น วันนี้วันอาทิตย์ครับ ... เมืองหยั่งกะเมืองร้างแหนะ มีแต่ตึก ไม่มีคน ไม่มีร้านขายของ ... จริง ๆ มีอยู่ร้านนึงใกล้ ๆ โรงแรม แต่ว่ามันปิดวันอาทิตย์หนะ
ส่วน ตัวโรงแรม Hotel Centrale เนี่ย ก็ไม่ใช่โรงแรมหรูหราอะไรเลย ไว้หาสายต่อกับกล้องได้แล้วจะเอารูปให้ดู ลิฟท์ยังมีแบบที่กดปุ่มแล้วไฟไม่ขึ้น ข้างในก็ไม่มีจอบอกว่าอยู่ชั้นไหนแล้ว ...
แต่สิ่งแปลก ๆ เท่ ๆ ก็มีอยู่บ้างนะ คือ ลิฟท์เค้า มีชั้น 0 กับ -1 ด้วยอะ ... เขียนหยั่งงี้บนปุ่มให้กดเลยนะ
แล้วก็ ในห้องพักสำหรับสองคนเนี่ย ... ประตูห้องน้ำไม่มีล็อก
และที่ขาดไม่ได้ ... มันมี Internet ให้ใช้ด้วย !!! มีได้ไงไม่รู้
ตอนนี้ก็ ... สี่โมงยี่สิบสามละ (เหลือบไปเห็นนาฬิกาของเครื่องคอมพ์ ... 9:38 PM แล้วนี่หว่า) พอดีกว่า ไปคุย msn ละ ไว้มีอะไรจะมาบอกเรื่อย ๆ นะ
Tuesday, May 02, 2006
กำลังจะไปยุโรป
วันที่ 6 - 20 เดือนนี้ จะไป Rome กับ Frankfurt หละ ไว้จะถ่ายรูปมาให้ดูกันบ้าง ... (กลับมา จะ update ละ)
Thursday, April 13, 2006
Sunday, February 05, 2006
คนชอบ คนไม่ชอบ ...
คนที่ชอบเรา = คนที่พอใจในสิ่งที่เราทำ
คนที่ไม่ชอบเรา = คนที่ไม่พอใจในสิ่งที่เราทำ
คนที่รู้สึกเฉย ๆ กับเรา = คนที่ไม่คิดว่าต้องสนใจการกระทำของเรา
คนที่ไม่ชอบเรา = คนที่ไม่พอใจในสิ่งที่เราทำ
คนที่รู้สึกเฉย ๆ กับเรา = คนที่ไม่คิดว่าต้องสนใจการกระทำของเรา
ระดับความพอใจที่ X รู้สึกต่อ Y
- ความพอใจจากประสบการณ์ตรง: Y ช่วย X
- ความพอใจจากการวิเคราะห์: X รู้สึกว่า Y ทำสิ่งที่ X เห็นว่าดี
- เป็นที่พี่งทางใจ
- ช่วยแก้ปัญหา
- ให้เงิน
- ซ่อมถนนแถวบ้าน
- พัฒนาชุมชนแถบใกล้เคียง
- ฯลฯ
- ทำให้คนทั้งโลกมีความสุขมากขึ้น
- ทำให้คนหลาย ๆ คน รวยขึ้น
- ทำให้คนที่เราไม่ชอบ เสียหาย
- ปราบยาเสพติดได้
- สร้างงานให้ชนชั้นล่าง
- ทำให้เศรษฐกิจดีขึ้น
- ฯลฯ
ความพอใจของคนหมู่มาก
มันเป็นเรื่องปกติที่ เราไม่สามารถสร้างประสบการณ์ตรงกับคนหมู่มาก (เช่น ทั้งประเทศ) ได้ วิธีที่จะทำให้คนส่วนใหญ่พอใจเรา ก็คือ การให้ข้อมูล
เพื่อที่จะให้ข้อมูลด้านดีของเรา ไปถึงคนส่วนใหญ่ได้ เราก็ควรจะควบคุมสื่อของข้อมูล ที่เข้าถึงคนส่วนใหญ่ได้ (เช่น โทรทัศน์ วิทยุ หนังสือพิมพ์ ฯลฯ)
วิธีควบคุมสื่อที่เข้าถึงคนส่วนใหญ่ได้ ก็มีมากมายหลายอย่าง เช่น
- เป็นเจ้าของสื่อเอง
- ควบคุมสื่ออื่นทางตรง (ซื้อ)
- ควบคุมผู้ที่ทำงานให้สื่ออื่น
ใช้คนที่เราควบคุมได้ ไปเผยแพร่ข้อมูล (ที่อาจจะไม่จริง) เพื่อให้คนกลุ่มใหญ่พอใจ
ข้อมูลดึงอารมณ์
วิธีการสร้างข้อมูลสนับสนุนหรือบ่อนทำลาย มักจะเน้นที่การดึงอารมณ์ ตัวอย่างการสร้างภาพขอความเห็นใจ เช่น
- กลุ่มคนที่บ้าคลั่ง กำลังด่าทอ สาปแช่งเรา
- เด็ก คนแก่ คนป่วย คนพิการ คนจน มาให้กำลังใจเรา
ประชาธิปไตย
ประเด็นสำคัญของประชาธิปไตยก็คือ จำนวนคนที่ชอบเรา ดังนั้น วิธีที่กล่าวไว้ จึงเป็นวิธีที่นักการเมือง ในประเทศประชาธิปไตย นิยมมากที่สุด
แล้ว สิ่งที่ประชาชนควรกระทำหละ?
โดยอุดมคติแล้ว หน้าที่ของประชาชนก็คือ วิเคราะห์ประสบการณ์และข้อมูลต่าง ๆ แล้วตัดสินใจ เพื่อผลประโยชน์สูงสุดของประเทศชาติ
แต่ ถ้าทุกคนคิด "ถูกต้องที่สุด" เหมือนกัน (และสิ่งที่ถูกต้องที่สุดมีเพียงหนึ่งเดียว) การเลือกตั้งทุกครั้งก็คงจบลงที่ มีผู้สมัครรับเลือกตั้งเพียงผู้เดียวเท่านั้นที่ได้คะแนนไม่เป็นศูนย์
แน่นอนว่า สิ่งนี้ไม่สามารถเกิดขึ้นจริงได้ เพราะสิ่งที่ "ถูกต้องที่สุด" มันไม่มีนิยามที่ชัดเจน แต่ละคนก็จะมองแตกต่างกัน สิ่งที่ประชาชนพอจะทำได้ก็คือ พยายามเลือกสิ่งที่ "น่าจะถูกต้องที่สุด" ซึ่งตัวเลือกของแต่ละคน ก็มีสิทธิ์ที่จะแตกต่างกัน
สรุปก็คือ เราควรจะถามตัวเองเสมอ ๆ ด้วยเหตุผล เพื่อเตือนตัวเองให้ตัดสินใจใกล้เคียง "อุดมคติ" มากที่สุด ตัวอย่างคำถามก็เช่น
- ถ้าเราพอใจ X จากประสบการณ์จริง แสดงว่า X ทำเช่นเดียวกันกับผู้อื่นหรือไม่?
- ถ้าเราพอใจ X จากประสบการณ์จริง ผู้อื่นจะพอใจกับประสบการณ์แบบเดียวกันหรือไม่?
- ข้อมูลเกี่ยวกับ X ที่เราได้รับ มีโอกาสเป็นจริงหรือเท็จมากแค่ไหน?
- เรามีอคติหรือไม่ ในการวิเคราะห์ข้อมูลเกี่ยวกับ X?
- ถ้าเราพอใจข้อมูลที่ได้รับเกี่ยวกับ X ผู้อื่นจะพอใจข้อมูลเดียวกันนี้หรือไม่?
- ฯลฯ
ผู้สนับสนุนส่วนเกิน
คนที่เชี่ยวชาญเรื่องเกี่ยวกับ Y มักจะไม่ยอมรับ X เมื่อ X เป็นอะไรซักอย่างใน Y
(ที่ใช้คำว่า "มักจะ" ก็เพราะว่า มันไม่ใช่ทุกครั้ง)
ตัวอย่างเช่น
- คนที่ดูหนังมามาก ๆ มักจะวิจารณ์หนังเรื่องใหม่ ๆ ในทางลบ
- คนที่เห็นเสื้อบอลมามาก ๆ จะไม่ชอบเสื้อบอลรุ่นใหม่
- ฯลฯ
(อย่างไรก็ตาม การไม่ยอมรับ ไม่ใช่สิ่งที่ผิด)
เรื่องที่น่าแปลกก็คือ ข้อความตรงข้ามของประโยคข้างบน ก็เป็นจริงค่อนข้างบ่อย
คนที่ไม่เชี่ยวชาญเรื่องเกี่ยวกับ Y มักจะยอมรับ X เมื่อ X เป็นอะไรซักอย่างใน Y
เหตุผลที่เป็นเช่นนี้ ก็อาจจะเป็นเพราะว่า โดยธรรมชาติของมนุษย์ ไม่ชอบความขัดแย้ง ดังนั้น เมื่อมีใครเสนออะไรขึ้นมา เราก็มักจะไม่อยากไปโต้แย้งเขา นอกจากเราจะรู้จริง ๆ ว่ามันไม่ดีอย่างไร (คือ เราเชี่ยวชาญเรื่อง Y หรืออย่างน้อย เราคิดว่าเราเชี่ยวชาญเรื่อง Y)
(การยอมรับ ก็ไม่ใช่สิ่งที่ผิด)
ผลลัพธ์อย่างนึงของประโยคนี้ก็คือ คนที่ไม่ได้ใส่ใจการเมือง มีแนวโน้มจะยอมรับรัฐบาล
เมื่อผนวกกับ ความกลัวความเปลี่ยนแปลง ซึ่งเป็นธรรมชาติของมนุษย์อีกอย่าง เราจึงรู้ว่า
คนที่ไม่ได้ใส่ใจในการเมือง มีแนวโน้มที่จะยอมรับรัฐบาล และไม่คิดล้มล้างรัฐบาล
คนเหล่านี้ เป็น "ผู้สนับสนุนส่วนเกิน" ของรัฐบาล
รัฐบาลที่ฉลาด จะเห็นช่องว่างตรงนี้ แล้วพยายามดึงคนกลุ่มนี้เป็นพวกให้มากที่สุด เพราะว่า มีปริมาณมาก และคล้อยตามง่าย
อย่างไรก็ตาม ผู้สนับสนุนส่วนเกิน ไม่ใช่ผู้ที่ขัดขวางแนวทางของประชาธิปไตย แต่เป็นส่วนประกอบที่เกิดขึ้นจาก ธรรมชาติของประชาธิปไตย
คนเดินขบวน
คนส่วนใหญ่ มักจะมีหน้าที่ประจำของตัวเองอยู่แล้ว การที่จะต้องละทิ้งหน้าที่ตัวเองเพื่อไปทำอะไรซักอย่าง ที่มัน "ไม่ปกติ" แสดงว่าสิ่งที่ไปทำนั้น จะต้องสำคัญมาก ๆ รัฐบาลควรมองพวกที่เดินขบวนเป็นข้อมูลที่ต้องสนใจ
การตั้งตัวเป็นศัตรูกับพวกที่เดินขบวน แล้วไม่รับฟังสิ่งใด ๆ จากคนเหล่านี้ ถือว่าเป็นสิ่งที่ไม่สมควรกระทำ รัฐบาลใด ๆ ควรจะเข้าใจว่า ปกติแล้ว คนจะไม่พยายามมาเหนื่อยในเรื่องแบบนี้ ถ้ามีขบวนเกิดขึ้น รัฐบาลควรจะถามว่า เขามาเดินขบวนกันทำไม จะได้ไปแก้ปัญหาให้ได้
การสลายกลุ่มผู้ประท้วง โดยการจ้างกลุ่มคนก่อความไม่สงบ (เช่น จ้างหญิงโสเภณีมาตีคนแก่ จ้างชาวบ้านมาแสดงการเผารูปผู้นำกลุ่มเดินขบวน ฯลฯ) เป็นสิ่งที่เลวร้ายยิ่งกว่าการไม่ฟังยิ่งนัก
อย่างไรก็ตาม กลุ่มผู้ประท้วง หรือกลุ่มคนก่อความไม่สงบ อาจจะถูกว่าจ้างมาจากฝั่งใดก็ได้ เช่น กลุ่มผู้ประท้วง อาจจะถูกว่าจ้างโดยฝ่ายค้าน หรือกลุ่มคนก่อความไม่สงบ อาจจะถูกว่าจ้างโดยกลุ่มผู้ประท้วงเอง เพื่อสร้างภาพที่ไม่ดีต่อรัฐบาล ดังนั้น เป็นหน้าที่ของคนทุกคนที่ได้รับข้อมูลเหล่านี้ ที่จะต้องวิเคราะห์ด้วยเหตุผล อย่าคล้อยตามไปกับปริมาณข้อมูล
ถึงแม้ประชาธิปไตยจะเน้นสิทธิความเท่าเทียมกันของบุคคล แต่ตัวตนของผู้เดินขบวนก็เป็นข้อมูลที่ไม่ควรละเลย โดยเฉพาะ ในกรณีที่ผู้เดินขบวน เป็นคนมีอายุ มีฐานะการงาน มีครอบครัว สิ่งนี้แสดงว่า ถึงแม้จะมีภาระรับผิดชอบมากมาย ยังยอม "เสี่ยงชีวิต" มาเดินขบวน
ตัวอย่างเช่น ผู้เคยที่ประท้วงรัฐบาลในอดีต (เมื่อยังเป็นนักศึกษา) มีแนวโน้มที่จะเป็นผู้เชี่ยวชาญการเมือง สูงกว่าคนทั่วไป และมีแนวโน้มที่จะ "รักชาติ" มากกว่าด้วย การเรียกผู้มีอายุเหล่านี้ว่าเป็น "นักธุรกิจที่ถูกขัดผลประโยชน์" จึงฟังดูไม่สมเหตุสมผล (ในทางอุดมคติ ไม่ควรจะมี "นักธุรกิจที่ถูกขัดผลประโยชน์" ด้วยซ้ำ)
Sunday, January 29, 2006
Saturday, January 28, 2006
เกือบโกหก ... ?
ประเด็นมันอยู่ที่ว่า หลาย ๆ คน คิดว่า คนที่จะเข้าวิศวะจุฬา ฯ ได้เนี่ย จะต้องขยันเรียนสุด ๆ (อย่างน้อยก็ ตอน ม. ปลาย) และคนที่จะได้เกียรตินิยมอันดับ 1 เนี่ย มันต้องขยันโคตร ๆ ๆ ๆ
เรื่อง 2 เรื่องต่อไปนี้ เป็นเหตุการณ์ตัวอย่าง (จริง ๆ มีมากกว่า 2 ครั้ง) ซึ่งอาจจะไม่ได้ตรงกับเหตุการณ์จริง 100% นะ
เรื่องที่ 1
เพื่อนผมคนนึง เคยเป็นอันดับต้น ๆ ของโรงเรียนตอนมัธยม เค้าอยู่วิศวะจุฬา ฯ เหมือนกัน (ตอนนั้นยังเรียนอยู่) แต่เกรดเค้าไม่ค่อยดี (คือ ใกล้ ๆ 3 ... บางคนก็บอกว่าดีแล้ว) พอไปคุยกะแม่เค้า แม่เค้าถามเกรดผม ... พอบอกไปปุ๊บ (ตอนนั้น 3.85) ก็ได้คำพูดตอบกลับมาทันทีว่า
อ่านหนังสือทบทวนทุกวันเลยสิ ดูอย่างเพื่อนไว้บ้างนะ
ฮ่วย ... พูดไม่ออก ... เพื่อนผมก็พูดไม่ออกด้วยอะ ก็เค้ารู้แหละ ว่าผมเป็นไง ให้เอาอย่างผมก็ยิ่งซวยสิ ... สุดท้ายก็ได้แค่ ผงกหัวแล้วพูด "ครับ ๆ" อย่างเดียว
เรื่องที่ 2
มีแม่ของเด็กม.ปลายคนนึง (คือ เค้ารู้จักกับญาติผมหละ) ถามว่า
อยู่วิศวะจุฬา ฯ ได้เนี่ย ต้องขยันมาก ๆ เลยสิ
จะให้ปฏิเสธหรอ? ... คือ ในใจก็รู้ตัวว่า ไม่เคยขยันเรียนอย่างที่คนอื่น ๆ เค้าพูดกัน แต่ไงดีหละ ... ก็เอาเป็นว่า สิ่งที่เราทำ ๆ ไป คนอื่นคงเรียกได้ว่า "ขยันมาก ๆ" หละมั้ง
เลยตอบแบบคลุมเครือไป ประมาณว่า
ครับ ตอนเอ็นทรานซ์เนี่ย ก็ต้องดูหนังสือเยอะ
ในใจก็แอบคิดว่า ไอ้คำว่า "เยอะ" เนี่ย ... มันไม่มีนิยามที่เฉพาะเจาะจง คงไม่เรียกว่าโกหกนะ ... แต่แล้ว เค้าก็ถามต่อมาว่า
ดูหนังสือก่อนสอบกี่เดือนหละ?
เวรกรรม ... จะตอบว่าสัปดาห์เดียวได้มั้ยหละเนี่ย ... ขอเลี่ยง ๆ อีกหน่อยละกันนะ
ก็ ... เตรียมตัวสอบเกือบทั้งปีหละครับ
"เตรียมตัวสอบ" เนี่ย คิดในใจว่า รวมเรื่องสมัครสอบไปด้วยละกัน คิดว่า ตั้งแต่เตรียมตัวสอบครั้งแรก ถึงการสอบครั้งที่สอง มันคงเรียกว่า "เกือบทั้งปี" ได้มั้ง ...
ยัง ยัง ... ยังไม่รอด ...
แล้วดูหนังสือวิชาเลขยังไงหรอ?
แป่วววว ... เล่นบอกวิชามางี้ ... ไม่ได้ดูอะ ... อ้อ ๆ แต่ ที่โรงเรียนมีโจทย์ (การบ้านงี่เง่า ๆ หนะ) ให้ทำเรื่อย ๆ หนิ
ก็ทำโจทย์เยอะ ๆ หละครับ
ตอนนี้ ในใจก็คิดว่า แค่มากกว่า 0 คงเรียกว่า "เยอะ ๆ" ได้มั้ง ... แต่มันเริ่มขัดกับอุดมการณ์ตัวเองแล้วอะ ไม่เคยคิดเลย ว่าจะบอกให้คนอื่นท่องรูปแบบโจทย์ แต่เค้าต้องคิดงั้นแน่เลย และแล้ว เค้าก็บอกว่า
เห็นมั้ยลูก ทำโจทย์เยอะ ๆ นะ เอาให้ครบทุกแบบเลย
- -'' ... ซะงั้น ... นี่มันเรียนผิดวิธีเลยนะ ...
Monday, January 16, 2006
Sunday, January 08, 2006
อาวละ ... สรุป blog
blog ที่เกิดใหม่ตอนปีใหม่ มีดังนี้...
Another Tunoblog - blog เรื่องไร้สาระ
Tunology - blog วิชาการ
(ใครที่อ่านสิ่งที่เคยเขียนไว้ที่นี่ (Tunoblog) ไม่ค่อยรู้เรื่อง ลองไปดูใหม่ที่ Tunology นะ อาจจะรู้เรื่องมากขึ้น)
Tunosong - blog เกี่ยวกะดนตรี
Tunology - blog วิชาการ
(ใครที่อ่านสิ่งที่เคยเขียนไว้ที่นี่ (Tunoblog) ไม่ค่อยรู้เรื่อง ลองไปดูใหม่ที่ Tunology นะ อาจจะรู้เรื่องมากขึ้น)
Tunosong - blog เกี่ยวกะดนตรี
แต่ยังไม่เลิกเขียนอันนี้นะ แค่จะ update น้อยลง (เยอะเลย)
อัตราการ update ของทุก blog รวมกัน ก็คงจะน้อยกว่า blog นี้ในอดีตอยู่ดี :P
Wednesday, January 04, 2006
ไปเล่นมาเพียบเลย ...
จะย้ายเรื่องวิชาการไปที่ Tunology แล้วนะ ส่วน Tunoblog อันนี้ ก็คงจะซีเรียสน้อยลงละ
Another Tunoblog เขียนเป็นภาษาอังกฤษนะ
แล้วก็ เรื่องดนตรี กับเพลงที่เอาให้ฟัง จะย้ายไปอยู่ที่ Tunosong หละ
ของ blogsource ไม่เอาแล้ว ห่วยกว่า blogger อะ ...
แล้วอยู่ดี ๆ ใจ๋ก็มาบอกว่า ให้ไปทำที่ multiply.com ... มันมีเนื้อที่ไม่จำกัดอะ ...
ย้ายอีกทีดีมั้ยเนี่ย
Another Tunoblog เขียนเป็นภาษาอังกฤษนะ
แล้วก็ เรื่องดนตรี กับเพลงที่เอาให้ฟัง จะย้ายไปอยู่ที่ Tunosong หละ
ของ blogsource ไม่เอาแล้ว ห่วยกว่า blogger อะ ...
แล้วอยู่ดี ๆ ใจ๋ก็มาบอกว่า ให้ไปทำที่ multiply.com ... มันมีเนื้อที่ไม่จำกัดอะ ...
ย้ายอีกทีดีมั้ยเนี่ย
Sunday, January 01, 2006
Wednesday, December 28, 2005
Tuesday, December 27, 2005
ม่ายหวายแล้ววววววว!!!
เขียนบ่อย ๆ ไม่ไหวแล้วอะ ... งานมหาศาล ... หยั่งงี้ยังเรียกว่าว่างงานได้มั้ยเนี่ย
แต่ยังไม่เลิกเขียนนะ!
Monday, November 21, 2005
ถึงคราวต้องสร้าง Virtual Machine แล้ว (พื้นฐาน)
เพื่อให้เห็นภาพ ว่าที่ผ่าน ๆ มา มันเป็นอะไร คราวนี้ มาลองสร้าง Virtual Machine กันเถอะ ... มาสรุปสิ่งที่ Virtual Machine ควรจะมีก่อน ... ครั้งนี้คิดสำหรับ process เดียวก่อนนะ
Memory Units
เพื่อให้สามารถสร้าง memory module ได้ เราต้องกำหนดไว้ก่อนว่า แต่ละ word มีขนาดเท่าไหร่ ... สมมติเลยละกันนะ ว่า
ตำแหน่งของ memory 1 ตำแหน่ง จะเก็บข้อมูลได้ 1 byte
ขนาดของ instruction = 4 byte
ขนาดของ instruction = 4 byte
Process Space
- PC - Program Counter
- Memory - แบ่งเป็น
- Stack
- SP - Stack Pointer
- BP - Base Pointer
- Heap
- MA - Memory Address
- AC - Accumulator
- FP - Frame Pointer
- load: AC ← mem[MA]
- store: mem[MA] ← AC
- push X: SP ← SP - 4; mem[SP] ← X
- pop X: X ← mem[SP]; SP ← SP + 4
ก่อนอื่น ตกลงกันก่อนว่า ส่วนของ OPCODE เราจะยังไม่ใส่ตัวเลขลงไป แต่สมมติว่ามันกินเนื้อที่ 4 byte (เพื่อให้ง่ายเวลา implement จริงเป็นวงจรด้วย) instruction set ที่เราต้องทำ มีสามกลุ่ม คือ
Fundamental Instructions
PUSH X
- คำสั่งนี้ พิเศษกว่าคำสั่งอื่นตรงที่มันมี operand ด้วย ... ดังนั้น ขนาดของคำสั่งนี้จะต้องรวม X ลงไปด้วย ... เราจะกำหนดให้ 4 byte แรกเป็น opcode และ 4 byte หลังคือ X รวมกันเป็น 8 byte ต่อการ PUSH 1 ครั้ง
- การทำงาน: push X
- การทำงาน: push BP
- การทำงาน: pop MA; load; push AC
- การทำงาน: pop AC; pop MA; store
- การทำงาน: pop PC
- การทำงาน: pop AC; if AC > 0, pop PC, else pop AC
- การทำงาน: pop AC; if AC < 0, pop PC, else pop AC
- การทำงาน: pop AC; if AC = 0, pop PC, else pop AC
- การทำงาน: pop AC; if AC ≠ 0, pop PC, else pop AC
- การทำงาน: pop AC; push PC + 4; push BP; BP ← SP; PC ← AC
- การทำงาน: pop AC; SP ← BP; pop BP; pop PC; push AC
คำสั่งในกลุ่มนี้มีสองคำสั่งคือ ALLOC กับ FREE การทำงานของมันจะพิเศษหน่อย เพราะมันเป็น OS-Level Instruction ดังนั้น จะไม่สามารถ implement เป็น hardware ได้ตรง ๆ
ALLOC
- การทำงาน: pop AC; AC ← malloc(AC); push AC
- การทำงาน: pop AC; free(AC)
พวกนี้ จะมีเยอะเท่าไหร่ก็ได้ ... หลัก ๆ จะมีสองกลุ่มคือ unary กับ binary แต่ถ้าจะทำเพิ่ม ก็ทำได้เรื่อย ๆ นะ
NEG
- การทำงาน: pop AC; push -AC
- การทำงาน: pop MA; pop AC; push AC + MA
- การทำงาน: pop MA; pop AC; push AC - MA
- การทำงาน: pop MA; pop AC; push AC * MA
- การทำงาน: pop MA; pop AC; push AC / MA
- การทำงาน: pop MA; pop AC; push AC mod MA
NOT
- การทำงาน: pop AC; push ¬AC
- การทำงาน: pop MA; pop AC; push AC ∧ MA
- การทำงาน: pop MA; pop AC; push AC ∨ MA
- การทำงาน: pop MA; pop AC; push AC ↔ MA
- การทำงาน: pop MA; pop AC; push ¬(AC ↔ MA)
- การทำงาน: pop MA; pop AC; push ¬(AC ∧ MA)
- การทำงาน: pop MA; pop AC; push ¬(AC ∨ MA)
Sunday, November 20, 2005
มาลองทำ Assembler กัน (Process Space)
ลองสมมติว่า เราเขียนโปรแกรมมา คอมไพล์เสร็จ มันเป็นก้อน object code หน้าตาคงที่ ...
คำสั่ง JMP กับ CALL หละ? ตำแหน่งของการกระโดดมันคงที่หนิ ... แสดงว่า ถ้าเราเอา code เราไปวางไว้ที่อื่น (คือ address เริ่มต้นเปลี่ยนไป) มันก็จะทำงานไม่ถูกน่ะสิ!!!
Frame Pointer
ทางแก้ก็คือ แก้ที่ CPU ของเรา ให้ทุกครั้งที่ทำคำสั่งที่เกี่ยวกับ memory ให้เอาเลขที่ได้ ไปบวกกับ FP ก่อน แค่นี้ก็เรียบร้อย ... ว่าแต่ FP นี่มันจะเก็บไว้ที่ไหนหละ? ... ก็กำหนด Register ขึ้นมาอีกตัวสิ
Process Space
ดังนั้น เพื่อให้การทำงานในแต่ละ process ถูกต้อง เราจะเก็บค่า FP ปะติดกับ object code ไว้สำหรับแต่ละ process ... ค่า FP นั้น จะรู้ในเวลาที่ load โปรแกรมลงใน memory
พอถึงเวลาที่ process นั้นจะทำงาน เราก็เพียงแค่ load ค่า FP ของ process นั้นกลับคืนมา การทำงานก็จะถูกต้องแล้ว
Cross-Process Communication
แล้ว เราจะทำให้ process ต่าง ๆ ติดต่อกันได้ยังไงหละ?
วิธีที่เค้านิยมทำกัน จะมีอยู่ 2 แบบคือ
- Messaging - ติดต่อผ่าน OS
- Shared Memory - ขอ OS ให้เปิดช่องการติดต่อโดยตรง
รายละเอียดจริง ๆ ของสองอย่างนี้ จะยังไม่พูดถึงตอนนี้ละกัน ... ไว้หลังจากทำ Virtual Machine กับ Assembler ได้ก่อน
Saturday, November 19, 2005
มาลองทำ Assembler กัน (Return Value)
Return Value Problem
สมมติว่า มี code ภาษา C แบบนี้
int Succ(int a)
{
return a + 1;
}
พอแปลงเป็นภาษา Assembly จะได้
Succ:
REF a -2
PUSH a
LOAD
PUSH 1
ADD
RETURN
ไม่มีปัญหา แต่ถ้าในฟังก์ชัน มีตัวแปรภายในอยู่หละ?
int Double(int a)
{
int x = a;
return a + x;
}
ลองแปลงเป็น Assembly ดู
Double:
REF a -2
VAR 1
REF x 1
PVAR x
PVAR a
LOAD
STORE
PVAR a
LOAD
PVAR x
LOAD
ADD
???
???
RETURN
ที่ใส่ ??? ไว้ก็คือ เราจะ RETURN เลยไม่ได้ เพราะเรายังไม่ได้เรียก FVAR แต่ถ้าเราเรียก FVAR เนี่ย ค่าที่เราต้องการจะ RETURN มันก็จะหายไป เราจะทำยังไงหละ?
เรารู้ว่า ค่าที่จะถูก RETURN ออกไป จะต้องอยู่ในตำแหน่ง BP - 1 แน่ ๆ ดังนั้น เราก็สามารถแก้ปัญหานี้ได้โดย กำหนดตัวแปรที่ตำแหน่ง BP - 1 ให้มันเกินไว้ตัวนึง จะได้เป็น
Double:
REF a -2
PUSH 0
REF rv 1
VAR 1
REF x 2
PVAR x
PVAR a
LOAD
STORE
PVAR rv
PVAR a
LOAD
PVAR x
LOAD
ADD
STORE
FVAR
RETURN
แต่ ... แบบนี้มันยุ่งยากจัง ... เรากำหนดคำสั่งใหม่มันจะง่ายกว่านะ ... ก็สมมติซะว่าคำสั่ง RETURN มันจะรวม FVAR ไปด้วยเลย แบบนี้
RETURN
- POP ค่า Return Code ออกมาเก็บไว้ก่อน
- ถ้า SP ≠ BP ก็ POP ค่าอื่น ๆ ทิ้งไปเรื่อย ๆ จนกว่า SP = BP
- POP ค่ามาใส่ไว้ใน BP
- POP อีกค่ามาใส่ไว้ใน PC
- PUSH ค่า Return Code ที่เก็บไว้ คืนลงไปใน Stack
Double:
REF a -2
VAR 1
REF x 1
PVAR x
PVAR a
LOAD
STORE
PVAR a
LOAD
PVAR x
LOAD
ADD
RETURN
Friday, November 18, 2005
มาลองทำ Assembler กัน (Literal)
Literal
ลองดู code ภาษา C ข้างล่างนี้
int main()
{
char *msg = "ABC";
printf("%s\n", msg);
return 0;
}
เราจะแปลงมันเป็นภาษา assembly ได้แบบนี้
main:
VAR 1
REF msg 1
PVAR msg
PUSH literal0
STORE
PUSH literal1
PVAR msg
LOAD
PUSH printf
CALL
FVAR
PUSH 0
RETURN
literal0:
"ABC"
literal1: "%s\n"
printf:
...
สมมติว่า string "ABC" และ "%s\n" ใช้เนื้อที่ตัวละ 1 word เราจะได้ object code สุดท้ายแบบนี้
0000h: PUSH 0
0002h: PBASE
0004h: PUSH 1
0006h: SUB
0008h: PUSH 0024h
000Ah: STORE
000Ch: PUSH 0025h
000Eh: PBASE
0010h: PUSH 1
0012h: SUB
0014h: LOAD
0016h: PUSH 0026h
0018h: CALL
001Ah: PUSH 0
001Ch: MUL
001Eh: ADD
0020h: PUSH 0
0022h: RETURN
0024h: "ABC"
0025h: "%s\n"
0026h: ...
Thursday, November 17, 2005
มาลองทำ Assembler กัน (พื้นฐาน)
จริง ๆ แล้ว ภาษา assembly มันก็ภาษาเครื่องแหละ แต่มันเขียนสะดวกกว่านิดนึง ... อะไรที่เราควรจะกำหนดเพิ่มไว้ก่อนหละ? ก็เรื่อง label กับ ตัวแปรไง
Local Variables (อีกแล้ว)
สมมติว่า เราจะเขียนว่า
void f()
{
int x;
int y;
x = 0;
y = x + 500;
}
เดิมเราจะเขียนว่า
f:
VAR 2
PBASE
PUSH 1
SUB
PUSH 0
STORE
PBASE
PUSH 2
SUB
PBASE
PUSH 1
SUB
LOAD
PUSH 500
ADD
STORE
...
FVAR
PUSH ค่ามั่ว ๆ อะไรก็ได้
RETURNจะเห็นว่า การอ้างถึงตัว y จะต้องใช้ 3 คำสั่ง คือ
PBASE
PUSH 2
SUBเพื่อลดเรื่องยุ่งพวกนี้ เราก็กำหนดภาษาใหม่ แบบนี้
f:
VAR 2
REF x 1 (บอกให้ x = BP - 1)
REF y 2 (บอกให้ y = BP - 2)
PVAR x
PUSH 0
STORE
PVAR y
PVAR x
LOAD
PUSH 500
ADD
STORE
...
FVAR
PUSH ค่ามั่ว ๆ อะไรก็ได้
RETURNLabels
เราใช้ Label ไปหลายทีแล้วโดยที่ไม่ได้พูดถึง ... จริง ๆ แล้ว การจะกระโดดไปที่ label ต่าง ๆ จำเป็นจะต้องรู้ address ของ label เหล่านั้น ...
ดังนั้น Assembler ของเรา จะต้องมีความสามารถในการ แปลง label เหล่านั้น ให้เป็น address จริง ๆ
สมมติว่ามี code แบบนี้
int f()
{
int x;
int y;
do {
x = ReadFromSomewhere();
y = ReadFromSomewhere();
} while (x != y);
return 0;
}
จะเขียนเป็น Assembly ได้แบบนี้
f:
VAR 2
REF x 1
REF y 2
loop:
PVAR x
PUSH ReadFromSomewhere
CALL
PVAR y
PUSH ReadFromSomewhere
CALL
PVAR x
LOAD
PVAR y
LOAD
SUB
PUSH loop
JNZ
FVAR
PUSH 0
RETURN
ซึ่ง ตอนที่แปลเป็นภาษาเครื่อง เราจะต้องรู้ 3 อย่างคือ- ตำแหน่งเริ่มต้นของ f → สมมติว่าเป็น 1234h
- ตำแหน่งเริ่มต้นของ ReadFromSomewhere → สมมติว่าเป็น 5678h
- ขนาดของ instruction → สมมติว่าเป็น 2
1234h: PUSH
1236h: PUSH
1238h:
PBASE
123Ah:
PUSH 1
123Ch:
SUB
123Eh:
PUSH 5678h
1240h:
CALL
1242h:
PBASE
1244h:
PUSH 2
1246h:
SUB
1248h:
PUSH 5678h
124Ah:
CALL
124Ch:
PBASE
124Eh:
PUSH 1
1250h:
SUB
1252h:
LOAD
1254h:
PBASE
1256h:
PUSH 2
1258h:
SUB
125Ah:
LOAD
125Ch:
SUB
125Eh:
PUSH 1238h
1260h:
JNZ
1262h:
PUSH 0
1264h:
RETURN
คราวหน้า มาดูเรื่อง Literal กันนะ
Wednesday, November 16, 2005
มาลองออกแบบ Abstract Instruction Set กัน (ตอนต่อ)
ต่อจาก มาลองออกแบบ Abstract Instruction Set กัน (ตอนแรก) เลยนะ
ครั้งนี้ จะพูดถึงการคำสั่งอย่างย่อ ... เรียกว่า เป็น Higher-Level Assembly ละกัน ... เราจะพัฒนาคำสั่งไปเรื่อย ๆ แบบนี้ จนมันเป็นภาษาชั้นสูงไปเลย
Local Variables
เราสามารถจองตัวแปรบน stack ได้ด้วยคำสั่ง PUSH เช่น สมมติว่าเรามี code ภาษา C แบบนี้
void f()
{
int x;
int y;
x = 0;
y = x + 500;
...
}
เมื่อเราเรียกคำสั่ง f เราจะจองเนื้อที่บน stack ให้กับตัวแปร x และ y ได้ด้วยคำสั่ง PUSH แล้วเมื่อเราจะใช้ตัวแปรพวกนี้ เราก็อ้างถึงจากตำแหน่ง BP (x คือ BP และ y คือ BP - 1) ...
f:
PUSH ค่าเริ่มต้นของ x
PUSH ค่าเริ่มต้นของ y
PBASE
PUSH 0
STORE
PBASE
PUSH 1
ADD
PBASE
LOAD
PUSH 500
ADD
STORE
...
POP
POP
PUSH ค่าอะไรก็ได้สำหรับ return
RETURNแต่เอ๊ะ ... คราวที่แล้วบอกว่า ไม่มีคำสั่ง "POP" หนิ ... แล้วเราจะทำให้มัน POP ได้ไงหละ? ... มันก็ต้องอ้อม ๆ หน่อยแหละ ใช้ความรู้ที่ว่า อะไรคูณ 0 ก็ได้ 0 แล้วก็ อะไรบวก 0 ก็ได้ตัวเดิม เราจะสร้างคำสั่ง POP ได้จาก
PUSH 0
MUL
ADDแล้วถ้ามี POP หลาย ๆ ตัวติดกัน เราก็แค่เพิ่ม MUL ตรงกลางเข้าไป เช่น
จาก
POP
POP
POP
POP
POP
POP
กลายเป็น
PUSH 0
MUL
MUL
MUL
ADD
MUL
MUL
MUL
ADD
Abbreviated Form
เพื่อให้เขียนง่าย แทนที่เราจะเขียน PUSH ซ้ำ ๆ สำหรับตัวแปรหลาย ๆ ตัว เราจะเขียนว่า
VAR n
เพื่อหมายถึงการ PUSH เปล่า ๆ ไป n ครั้ง เป็นเนื้อที่ของตัวแปร n ตัว ส่วนการ POP เราก็จะเขียนว่า
FVAR
(ย่อมาจาก Free VAR) เพื่อหมายถึง PUSH 0, MUL, MUL, MUL, ..., ADD ที่มีจำนวน MUL เท่ากับ n ของคำสั่ง ALLOC ก่อนหน้านี้
Dynamic Allocation
เนื่องจาก ... การจองเนื้อที่สำหรับตัวแปรบน heap เป็นสิ่งที่ทำกันบ่อยมาก ๆ เราก็เลย สมมติว่ามีคำสั่งสำหรับทำงานนี้เลยละกัน
ALLOC
การทำงานคือ
- POP ค่าบนสุดของ Stack ออกมา ให้เป็นขนาด memory block ที่ต้องการ
- ไปค้นหาเนื้อที่ว่างจาก heap
- PUSH ค่า address คืนลงไปใน Stack
FREE
จะต้องการ POP ค่าจาก stack เพียงค่าเดียว คือ address
ตัวอย่างเช่น
void f()
{
int* x;
x = new int;
...
}
f:
VAR 1 (สมมติว่าขนาดของ pointer = 1)
PBASE
PUSH 1 (สมมติว่าขนาดของ int = 1)
ALLOC
STORE
...
FVAR
PUSH ค่าอะไรก็ได้สำหรับ return
RETURNสรุปคำสั่งตอนนี้
จริง ๆ คำสั่ง ALLOC กับ FREE มันไม่ใช่คำสั่งพื้นฐานที่ CPU ควรจะมีหรอกนะ มันเป็น OS-level Instruction หนะ วิธีสร้าง ALLOC กับ FREE จริง ๆ ไว้จะบอกทีหลัง แต่ตอนนี้สมมติว่ามีให้ใช้เลยละกัน
Minimal Instruction Set + ALLOC & FREE
PUSH
PBASE
LOAD
STORE
JPOS
CALL
RETURN
NAND
NEG
ADD
MUL
ALLOC
FREE
PBASE
LOAD
STORE
JPOS
CALL
RETURN
NAND
NEG
ADD
MUL
ALLOC
FREE
Abbreviations
JMP
JNEG
JZ
JNZ
NOT
AND
OR
XOR
IFF
SUB
DIV
MOD
VAR
FVAR
...
JMP
JNEG
JZ
JNZ
NOT
AND
OR
XOR
IFF
SUB
DIV
MOD
VAR
FVAR
...
แล้วจะมาเพิ่ม abbreviation อีกเรื่อย ๆ นะ
Tuesday, November 15, 2005
มาลองออกแบบ Abstract Instruction Set กัน (ตอนแรก)
ขอโทษล่วงหน้า ถ้าทำให้ใครบางคนอ่านเรื่องนี้ไม่รู้เรื่องตั้งแต่ต้น ...
บังเอิญว่า อยากจะเอาเรื่องเกี่ยวกับการออกแบบ Instruction Set ของ CPU มาให้ดู ๆ กันบ้างหนะ
Abstract Instruction Set
จุดประสงค์การออกแบบชุดคำสั่ง (Instruction Set) นี้ ไม่ใช่เพื่อให้มันประสิทธิภาพสูงสุด หรือว่าทำเป็นวงจรง่ายหรอกนะ แต่ อยากจะทำให้มันทำงานได้ครบ โดยที่มีคำสั่งน้อย ๆ มากกว่า
Chosen Design: Stack Machine
Stack Machine เป็นแนวคิดที่ว่า Operation ทั้งหลาย ทำบน Stack ... คิดว่าแบบนี้น่าจะทำให้ลดจำนวนคำสั่งลงได้เยอะ
ข้อเสียก็คือ การจะทำอะไรอย่างนึง มันต้องมีหลายคำสั่งน่ะสิ แล้วก็ การทำ Pipelining จะยากด้วย แต่ขอไม่สนเรื่องนี้ก่อน
เหตุผลสนับสนุนอีกอย่างนึงที่ทำให้เลือก Operation on Stack ก็คือ เวลาทำ compiler ให้แปล source code เป็น machine code เนี่ย มันจะค่อนข้างง่ายและตรงมาก (แต่ประสิทธิภาพก็ไม่ได้ดีเท่าไหร่แหละ)
First Two Opcodes: PUSH and POP
เวลาจะทำ Stack ใคร ๆ ก็ต้องคิดถึง Push กับ Pop แน่ ๆ เราก็กำหนดเลยละกันว่า เราจะมีสองคำสั่งนี้
ผลก็คือ เราสามารถสร้างให้คำสั่งอื่น ๆ ไม่รับ operand เองโดยตรงได้ เช่น
คำสั่ง A = B + C
Instruction Set ทั่วไป
ADD A, B, C
Stack-based Operation ของเรา
PUSH B
PUSH C
ADD
POP A
Instruction Set ทั่วไป
ADD A, B, C
Stack-based Operation ของเรา
PUSH B
PUSH C
ADD
POP A
ว่าแต่ว่า ... เราจะระบุสิ่งที่จะ PUSH กับ POP ได้ยังไงหละ?
Types of Operands
เนื่องจากเราจะลดความซับซ้อนให้เหลือน้อยที่สุด เราจะยอมให้มี operand ได้แค่แบบเดียวแบบ คือ
- Immediate
Required Registers
เราจะให้มี register เพียง 3 ตัว ที่สามารถยุ่งเกี่ยวได้ด้วย machine instruction คือ
- Program Counter (PC) = Address ของคำสั่งปัจจุบัน
- Base Pointer (BP) = Address แรกของ Local Variable ปัจจุบัน
- Stack Pointer (SP) = Address ของ Top-of-stack
สมมติว่า SP จะลดค่าเมื่อ PUSH และเพิ่มค่าเมื่อ POP นะ (ทำตามแบบที่เค้านิยมกัน)
Indirect Indexing: PBASE
เนื่องจาก Base Pointer (BP) เป็น register ที่ควรจะสามารถนำค่าไปบวก-ลบได้ ดังนั้น เราจึงควรจะสร้างคำสั่งที่ใช้อ่านค่า BP ดังนี้
PBASE = Push ค่าของ BP ขึ้น Stack
LOAD and STORE
เราจะกำหนดให้ คำสั่ง LOAD จะใช้ operand เป็นตัวบนสุดของ stack ตัวเดียว มีการทำงานคือ
- เอาค่าบนสุดของ stack ไปเป็น address อ้างอิง memory
- อ่านค่าจาก memory ในตำแหน่งนั้น
- เอาค่าที่อ่านได้ มาแทนที่ในตำแหน่งบนสุดของ stack (ที่เคยเป็น address)
- POP ตัวแรกออกจาก stack ใช้เป็น address อ้างอิง memory
- POP ตัวที่สองออกจาก stack ใช้เป็นค่าที่จะเขียนลง memory
- เขียนค่าที่ได้ (จากการ POP ครั้งที่สอง) ลงใน memory (address ได้จากการ POP ครั้งแรก)
สังเกตดี ๆ หละ ว่า จริง ๆ เราไม่ต้องมีคำสั่ง POP นะ!!!
Logical Functions: NOT, AND, OR, XOR, IFF
ถึงแม้ว่า จริง ๆ แล้วเราสามารถใช้แค่ NAND หรือ NOR เพียงอย่างเดียวได้ แต่ตรงนี้ ไม่ขอประหยัดจำนวน Opcode นะ เพราะว่ามันไม่ได้เป็นสาระสำคัญเท่าไหร่ (ถ้าอยากจะสร้างแบบประหยัด ให้มันมีแต่ NAND หรือมีแต่ NOR เวลาทำ compiler ก็จะเหนื่อยหน่อย เท่านั้นเอง)
Arithmetic Functions: NEG, ADD, SUB, MUL, DIV, MOD, EXP, LOG, ...
พวกนี้ก็เหมือนกัน ... จริง ๆ มีแค่ NEG ADD แล้วก็ MUL ก็น่าจะพอแล้ว แต่การประหยัดจำนวนคำสั่งตรงนี้ ก็ไม่ใช่สาระสำคัญเหมือนกัน ดังนั้นเราจะถือว่า คำสั่งพวกนี้ มีหมดเลย ก็แล้วกัน
Classical Modes of Addressing
เนื่องจาก Operand เรา มีแต่แบบ Immediate การอ้างถึง Operand ในลักษณะอื่น ๆ แบบที่เครื่องทั่ว ๆ ไปเค้าทำได้ มันจะต้องใช้หลายคำสั่งหน่อยนะ เช่น
Target: Value at memory address X
Abbreviation: [X]
How to PUSH that?
PUSH X
LOAD
Abbreviation: [X]
How to PUSH that?
PUSH X
LOAD
Target: Value at memory address BP + X
Abbreviation: [BP + X]
How to PUSH that?
PBASE
PUSH X
ADD
LOAD
Abbreviation: [BP + X]
How to PUSH that?
PBASE
PUSH X
ADD
LOAD
Target: Value at memory address (BP + value at X)
Abbreviation: [BP + [X]]
How to PUSH that?
PBASE
PUSH X
LOAD
ADD
LOAD
Abbreviation: [BP + [X]]
How to PUSH that?
PBASE
PUSH X
LOAD
ADD
LOAD
Target (in C): Array[Index]
Abbreviation: [BP + array + [BP + index]]
How to PUSH that?
PBASE
PUSH array
ADD
PBASE
PUSH index
ADD
LOAD
ADD
LOAD
Abbreviation: [BP + array + [BP + index]]
How to PUSH that?
PBASE
PUSH array
ADD
PBASE
PUSH index
ADD
LOAD
ADD
LOAD
Simple Branch Instructions: JMP, JPOS, JNEG, JZ, JNZ
- JMP: POP → PC
- JPOS: POP → เก็บไว้ แล้ว POP อีกที ถ้าได้ค่าเป็นเลขบวก (มากกว่า 0) ถึงจะกระโดดไปยัง address ที่เก็บไว้
- JNEG: คล้าย ๆ กับ JPOS แต่จะกระโดดถ้าค่าที่ POP ออกมาครั้งที่ 2 เป็นเลขติดลบ
- JZ: POP → เก็บไว้ แล้วก็ POP อีกที ถ้าได้ค่าเป็น 0 ถึงจะโดดไปยัง address ที่เก็บไว้
- JNZ: คล้าย ๆ กับ JZ แต่เงื่อนไขการกระโดดตรงกันข้าม
Subroutine: CALL, RETURN
คำสั่ง CALL จะวุ่น ๆ หน่อย เพราะมีการทำงานหลายขั้น คือ
- POP ค่า address ที่จะกระโดดไป เก็บไว้
- PUSH ค่า PC + 1 ไว้
- PUSH ค่า BP ไว้
- กำหนดค่าให้ BP = SP
- กำหนดค่าให้ PC = address ที่ POP ไว้ตอนแรก (ซึ่งก็คือ การกระโดดนั่นเอง)
- POP ค่า Return Code ออกมาเก็บไว้ก่อน
- POP ค่ามาใส่ไว้ใน BP
- POP อีกค่ามาใส่ไว้ใน PC (ซึ่งก็คือ การกระโดดกลับ)
- PUSH ค่า Return Code คืนลงไปใน Stack
Local Variable and Parameters
ถ้าต้องการส่งผ่าน parameter ให้กับ function เราก็จะใช้วิธี PUSH ใส่ stack ไว้ก่อน เช่น
- PUSH A
- PUSH B
- PUSH CustomAdd
- CALL
- ถ้า BP หลัง CALL = x
- SP ก่อน CALL จะ = x + 1
- ตำแหน่งของ B ก็เลย = x + 2
- และ ตำแหน่งของ A ก็ = x + 3
CustomAdd:
- PBASE
- PUSH 2
- SUB
- LOAD
- PBASE
- PUSH 3
- SUB
- LOAD
- ADD
- RETURN
ชุดคำสั่งเล็กสุด
PUSH
PBASE
LOAD
STORE
JPOS
CALL
RETURN
NAND
NEG
ADD
MUL
PUSH
PBASE
LOAD
STORE
JPOS
CALL
RETURN
NAND
NEG
ADD
MUL
คำสั่งลดความเหนื่อย
JMP
JNEG
JZ
JNZ
NOT
AND
OR
XOR
IFF
SUB
DIV
MOD
...
JMP
JNEG
JZ
JNZ
NOT
AND
OR
XOR
IFF
SUB
DIV
MOD
...
ตอนนี้เราก็ได้ Instruction Set คร่าว ๆ แล้ว แต่เราไม่พูดถึงขนาดของข้อมูลในแต่ละช่องของ Stack เลยนะเนี่ย ... ก็เลยเรียกว่า Abstract Instruction Set ไงหละ
Monday, November 14, 2005
การบวกลบเลขจำนวนเต็มไม่ติดลบ
เนื่องจาก การคิดเลขในฐานอะไรก็เหมือนกันหมด แต่เราอยากทำในกรณีที่มันเป็นฐาน 2 เพราะว่า คอมพิวเตอร์มันเป็นฐานสอง ... มาดูกันว่า การบวกเลขฐานสอง ทำกันยังไงนะ
จริง ๆ แล้ว ก็เหมือนกับฐาน 10 น่ะแหละ แต่มันง่ายกว่าด้วยซ้ำ เพราะว่า ผลลัพธ์มีแค่ 0 กับ 1 ดังนั้น ความเป็นไปได้ทั้งหมดของการบวกกันในแต่ละหลัก คือ ... (ตัวทด ใช้สีแดงนะ)
กรณีที่ไม่มีตัวทด (ตัวทด = 0)
0 + 0 = 00
0 + 1 = 01
1 + 0 = 01
1 + 1 = 10
0 + 0 = 00
0 + 1 = 01
1 + 0 = 01
1 + 1 = 10
กรณีที่มีตัวทด (ตัวทด = 1)
1 + 0 + 0 = 01
1 + 0 + 1 = 10
1 + 1 + 0 = 10
1 + 1 + 1 = 11
1 + 0 + 0 = 01
1 + 0 + 1 = 10
1 + 1 + 0 = 10
1 + 1 + 1 = 11
พอได้การบวกทุกแบบแล้ว เราก็ลองเอามาใช้ดู
ตอนนี้ก็บวกเป็นละ ... แล้วการลบหละ?
Sunday, November 13, 2005
เลขจำนวนเต็มไม่ติดลบ
ที่ผ่าน ๆ มา เราก็รู้กันไปเรียบร้อยแล้วเรื่อง การแปลงฐานเลข คราวนี้ก็ ขอตั้งข้อกำหนดเบื้องต้นไว้นิดนึงนะ คือ
ข้อมูลในคอมพิวเตอร์ จะอยู่ในรูปลำดับของเลขฐานสอง ที่มีความยาวจำกัด
ความยาวของลำดับ = จำนวน bit ของข้อมูล
ความยาวของลำดับ = จำนวน bit ของข้อมูล
แล้วก็ ขอกำหนดคำที่จะใช้เพื่อให้คุยกันง่ายขึ้น คือ
ข้อมูล n bit = เลขฐานสอง n หลัก
จำนวนเต็มไม่ติดลบ ที่สามารถแทนได้ด้วย n bit
คิดด้วยหลักการง่าย ๆ ว่า ข้อมูล 1 bit สามารถเป็นได้ 2 แบบ คือ 0 กับ 1 ดังนั้น
ข้อมูล n bit สามารถเป็นได้ 2n แบบที่แตกต่างกัน
เนื่องจาก จำนวนเต็มที่ไม่ติดลบ 2n ตัวแรก ก็คือ
0, 1, 2, ..., 2n - 1
ดังนั้น ข้อมูล n bit จะสามารถแทนจำนวนเต็มไม่ติดลบที่มีค่าน้อยกว่า 2n ได้ 1 ตัว
Byte
1 byte = 8 bits
ดังนั้น ข้อมูล 1 byte จะแทนจำนวนเต็มไม่ติดลบที่มีค่าน้อยกว่า 28 ได้ 1 ตัว
หมายเหตุ: แทนที่จะมองว่า 1 byte = เลขฐานสอง 8 หลัก เราอาจจะมองว่า 1 byte = เลขโดดฐาน 256 ก็ได้
เลขฐาน 16
ในโปรแกรมคอมพิวเตอร์พวกที่ให้เห็นค่าใน memory เรามักจะเห็นเลขฐาน 16 กันบ่อยพอควร แล้วมันก็จะอยู่เป็นคู่ ๆ ด้วย สาเหตุที่เค้านิยมเขียนเลขฐาน 16 อยู่เป็นคู่ ๆ ก็เพราะว่า มันสั้นกว่าการเขียนเป็นเลขฐานสอง แล้วที่มันใช้ได้ก็เพราะว่า
24 = 16 → เลขฐาน 16 ยาว 1 หลัก = ข้อมูล 4 bit
16 × 16 = 256 → เลขฐาน 16 ยาว 2 หลัก = ข้อมูล 1 byte
16 × 16 = 256 → เลขฐาน 16 ยาว 2 หลัก = ข้อมูล 1 byte
ดังนั้น
เลขฐาน 16 ยาว 2 หลัก = 1 byte
ตัวอย่าง
10102 = A16 = 10
11012 = D16 = 13
1010 11012 = AD16 = 173
11012 = D16 = 13
1010 11012 = AD16 = 173
ความนิยมอีกเรื่อง
เนื่องจาก การจะเขียนฐานเลขห้อย ๆ เนี่ย บางทีมันทำยาก (เช่น ในคอมพิวเตอร์สมัยก่อน หรือในหน้าจอของเครื่องอะไรก็ตามที่เป็น Text Mode) เค้าเลยนิยมเอา h ห้อยท้ายแทน (h มาจาก hexadecimal ← hexa + dec = 6 + 10) ส่วนเลขฐานสอง บางที่ก็เอา b ห้อยท้ายแทนการห้อยสอง เช่น
ADh = 173
11011010b = DAh = 218
11011010b = DAh = 218
จริง ๆ เครื่องหมายอื่น ๆ ก็มีอีก ไว้จะค่อย ๆ เอามาให้ดูบ้างละกันนะ