Tags:
Node Thumbnail

มีรายงานว่าผู้เล่นอย่างน้อยสองคนในเกม World of WarCraft มีหน่วยเงินในเกมถึงระดับ ทอง 214,748 หน่วย เงิน 36 หน่วย และทองแดง 48 หน่วย (ผมเข้าใจว่าเงินกับทองแดงเป็นหน่วยย่อยชุดละ 100 ของทองนะครับ) และพบว่าไม่สามารถมีปริมาณทองมากกว่านี้ได้อีก

เหตุผลทางโปรแกรมมิ่งก็คือผู้พัฒนาเกมได้ใช้ตัวแปรชนิด signed integer ขนาด 32 บิต ซึ่งมีขีดจำกัดอยู่ที่ 2^31 หรือ 2,147,483,648 นั่นเอง ก่อนหน้านี้เคยมีคนคาดการณ์ไว้แล้วว่ามีขีดจำกัดนี้อยู่ เพียงแต่เพิ่งเคยมีคนทำได้จริงในทางปฏิบัติ ความคิดเห็นใน Slashdot บอกว่าโปรแกรมเมอร์คงไม่คิดว่าจะมีใครมีเงินได้เยอะขนาดนี้ในเกม

ปัญหานี้เกิดกันบ่อยตามเว็บไซต์ดังๆ อย่าง Slashdot เองก็เคยมีปัญหาจำนวนคอมเมนต์เกิน 2^24, เบอร์รูปภาพใน Flickr เมื่อเกิน 2^31 จะมีปัญหากับ Flickr library บางตัว และล่าสุด Facebook เพิ่งปรับระบบไปใช้ user ID แบบ 64 บิต

ตอนเรียนเหมือนว่าจะไม่มีวันได้ใช้ เอาเข้าจริงมีเยอะเลย

ที่มา - World of WarCraft Insider

Get latest news from Blognone

Comments

By: au8ust
AndroidSymbianWindows
on 20 January 2008 - 18:18 #40502

เป็นกรณีศึกษาที่ดี แต่สงสัยว่าเค้าจะแก้ยังไงต่อ

By: lastone
Android
on 20 January 2008 - 18:20 #40503

แล้วตัวแปร array ที่กำหนดตำแหน่งด้วย int จะืำทำยังไงอ่ะครับ
array[int]

http://last0ne.multiply.com

By: kamthorn
ContributorAndroidUbuntu
on 20 January 2008 - 19:14 #40509 Reply to:40503

เอ่อ ถ้า array ใหญ่ขนาดนั้น ใส่ในฐานข้อมูลดีกว่าไหม

--


--

By: lastone
Android
on 20 January 2008 - 20:49 #40528 Reply to:40509

หมายถึงค่าที่อาจจะดึงมาจากเดต้าเบสแล้วมันก็ยังเกินน่ะครับ
แบบไม่ได้ใส่ where อะไรเลย ไม่รู้จะมีหรือป่าว
http://last0ne.multiply.com

By: kamthorn
ContributorAndroidUbuntu
on 20 January 2008 - 22:23 #40540 Reply to:40528

ประมาณ mysql_fetch_array() รึเปล่าครับ ถ้าข้อมูลเยอะ ๆ ก็ไม่ควรใช้อีกแหละครับหน่วยความจำจะไม่พอเอา

ปกติก็ใช้ mysql_fetch_row() เอา

--


--

By: Ford AntiTrust
ContributorAndroidBlackberryUbuntu
on 21 January 2008 - 01:04 #40557 Reply to:40540
Ford AntiTrust's picture

mysql_fetch_array -> จะได้ข้อมูลออกมาโดยอ้างอิงแบบ hashkey และ enumkey
mysql_fetch_assoc -> จะได้ข้อมูลออกมาโดยอ้างอิงแบบ hashkey
mysql_fetch_row -> จะได้ข้อมูลออกมาโดยอ้างอิงแบบ enumkey

ถ้าจะใช้แนะนำ assoc หรือ row ไปอย่างใดอย่างหนึ่งครับ แต่แนะนำว่า assoc จะดีกว่า เพราะการเขียน code นั้นสื่อความหมายได้ดีกว่า และเหมาะมากในกรณีที่มีการ sort ตัว column ใน table บ่อย ๆ การใช้ row อาจทำให้คลาดเคลื่อนได้ครับผม

ด้านความเร็วนั้นไม่แตกต่างกัน เพียงแต่ array จะได้ข้อมูลออกมาในหน่วยความจำเยอะกว่า 1 เท่าตัว เพราะมีทั้ง hashkey และ enumkey ครับ

ลอง print_r ดูก็น่าจะได้คำตอบ หรือดูใน manual เอาก็ได้ครับผม

Ford AntiTrust’s Blog

By: kaze
Writer
on 21 January 2008 - 12:37 #40602 Reply to:40557

ผมว่าคุณ lastone ไม่ได้หมายความอย่างนั้นนะครับ

สมมุติว่า Table มี column id กับ name สำหรับ mysql_fetch_array เราสามารถระบุให้เป็น hashkey ไปเลยก็ได้ครับ ถ้าใช้ $row = mysql_fetch_array($result, MYSQL_ASSOC); เวลาเรียกใช้จะเป็น $row["id"] กับ $row["name"] หรือ $row[0] กับ $row[1] ก็เปลี่ยนเป็น MYSQL_NUM หรือจะผสมกันก็ได้เป็น $row["id"] กับ $row[1] ก็ได้ ขึ้นกับว่าเราระบุหรือป่าวว่าเป็น MYSQL_NUM, MYSQL_ASSOC หรือ MYSQL_BOTH (ซึ่งเป็นค่า default ครับ ถ้าไม่ใส่ param ตัวที่ 2)

ถ้าใช้ $row = mysql_fetch_row($result); เวลาเรียกใช้จะเป็น $row[0] กับ $row[1]

ถ้าใช้ $row = mysql_fetch_assoc($result); เวลาเรียกใช้จะเป็น $row["id"] กับ $row["name"]

ซึ่งทั้งหมดเป็นการ return เพียง row เดียวใน database ครับ จำนวนช่อง array คือ จำนวน column ซึ่งไม่มี database ไหน ที่สามารถมี column ได้เกิน int ครับ (MySQL ได้ 3398 column) เพราะฉะนั้นไม่ต้องกลัวว่าจะอ้าง index เกินในกรณีนี้ โดยส่วนตัวผมจะใช้ mysql_fetch_object หรือใช้ DB_Object ใน PEAR

ส่วนที่คุณ lastone ถามนะครับ ก็ใช้ limit offset ให้การกำหนดช่วงที่จะ query ดีกว่าครับ แล้ววน query ไปเรื่อยๆ เอาค่าไปคำนวน เช่น SELECT * FROM account LIMIT 20 OFFSET 0 แต่ถ้าเอาไปแสดงผลก็ทำ pagination ดีกว่าครับ

By: kamthorn
ContributorAndroidUbuntu
on 21 January 2008 - 17:01 #40622 Reply to:40557

อ่อ ผม search มาดู อ่านแล้วเมา :-P

ตามคุณ Ford ว่ามาถูกต้องแล้วครับ :-D

--


--

By: nuuneoi on 20 January 2008 - 19:44 #40514

ดีนะไม่ Overflow

By: Framekung
iPhone
on 20 January 2008 - 20:32 #40523

คาดการณ์ผิดไปหน่อย

By: TiD
AndroidWindows
on 20 January 2008 - 20:40 #40526

เคยเจอใน RO แล้ว มีคน overflow จนติดลบไปแล้วด้วย

By: Wintermute on 20 January 2008 - 21:11 #40531

ผมเคยเล่น Transport Tycoon จนเงินติดลบเหมือนกันครับ

By: fujitarc on 20 January 2008 - 21:55 #40539

เป็นกรณีที่น่าสนใจอืม ^^":

By: ch-a-m-p on 20 January 2008 - 23:57 #40553

100 ทองแดง = 1 เงิน, 100 เงิน = 1 ทอง, 10000 ทองแดง = 1 ทอง นะครับ
(from gamemun.com/wow)

By: pruet
WriterAndroidRed HatUbuntu
on 21 January 2008 - 03:05 #40569
pruet's picture

ทำไมใช้ signed integer

By: tekkasit
ContributorAndroidWindowsIn Love
on 21 January 2008 - 09:57 #40588
tekkasit's picture

ปัญหา M2B (Money 2 billion) อุๆ

ผมไม่ทราบว่าทาง Blizzard แจ้งไว้ก่อนรึเปล่าว่ามี money cap อยู่ที่ 2 พันล้าน
มันเลยเป็นประเด็น เพราะผมว่า 200k คนธรรมดาก็มีน้อยแล้วมั้ง นี่เล่น 2 พันล้าน
เกิดปัญหาเงินเฟ้อเลยน่ะนี่
สงสัยในเกมส์มีช่องโหว่ในการได้เงินมาง่ายๆ
เลยมีคน farming กันอย่างสนุกสนาน

โดยส่วนตัวเปลี่ยนเป็น unsigned integer ก็ไม่ดีขึ้นหรอกครับ
เพราะแค่เอาสองคนเอาเงินมาให้ก็ชนเพดานใหม่อีกแล้ว
หรือแค่ฟาร์มกันอีกหน่อยเดี๋ยวก็ซวยใหม่

ตอนออกแบบ คงไม่คิดว่าใครจะมีเงินถึงสองพันล้านมั้ง

ทางแก้ที่น่าจะถาวรคือเปลี่ยนจาก 4 byte ไปเป็น 8 byte
แต่ว่ามันไม่ง่ายอย่างที่ว่าจะเป็น int32_t -> int64_t
ต้องไปเปลี่ยน cast มันทุกที่ในโค้ดรึเปล่า มีที่ไหนหลุดไปรึเปล่า
ท่านจะทำไงกับโครงสร้างข้อมูลที่มีอยู่
ฐานข้อมูลล่ะต้องอัพเดทรึเปล่า
การประมาณความจุพื้นที่ disk ล่ะต้องแปลนใหม่รึเปล่า

งานช้างนะครับ Y2K ก็ยาก M2B ก็เช่นกันครับ

By: kaze
Writer
on 21 January 2008 - 12:48 #40604

ถ้าเป็น C++ ก็ทำ class Money มาเลย attribute ก็เป็น list ของ int ถ้า int เต็มก็เพิ่ม int ใน list ซะ แล้ว overload operator เครื่องหมายบวก ลบ คูณ หารเลยได้หรือป่าวครับ (ไม่ได้เขียนนาน ลืมแล้ว >_<) ประมาณว่า class Money {   public:     int listInt[100];     Money operator +(Money val)     {       ...     } }

By: Sikachu
ContributoriPhoneIn Love
on 21 January 2008 - 21:05 #40638
Sikachu's picture

จำได้ว่าขนาด userid ของโปรแกรมที่ผมทำส่วนใหญ่ยังเป็น mediumint อยู่เลย ..
เพราะไม่คิดว่าคนจะเล่นเยอะ 555+

บล็อกของผม: http://sikachu.com


บล็อกของผม: http://sikachu.com

By: serene
Contributor
on 21 January 2008 - 23:14 #40649

ผมว่ามันเป็นปกติของโปรแกรมเมอร์นะที่จะคิดว่าใช้ตัวแปรแบบนี้ก็น่าจะเพียงพอสำหรับงานที่เราทำอยู่แล้ว ช่วยประหยัด byte ลงไปด้วย จะเผื่อมากไปก็สิ้นเปลืองโดยใช้เหตุ แต่อย่างว่าแหละครับ "ความแน่นอน ก็คือความไม่แน่นอน"

เอ แล้วตัวแปรประเภท byte ของผมมันจะ overflow ไหมหว่า ^_^"

By: Patrickz
WriterSymbian
on 22 January 2008 - 17:05 #40749

comment no. #40749 แล้ว.... คงอีกนานกว่าจะ overflow

Patrickz's blog | blog @ G2K | blog @ narisa | AsteriskThailand


Patrickz's blog|
linkedin

By: chaba_bkk
Android
on 22 January 2008 - 18:28 #40760

ผมว่า ง่ายที่สุด เพิ่มหน่วยเงิน อีกอันหนึ่งสิ เป็น มี ทองแดง, เงิน, ทอง แล้วเอาเป็น เพชร
น่าจะง่ายกว่า

It's my life. Open your mind for the future.