มีรายงานว่าผู้เล่นอย่างน้อยสองคนในเกม 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
Comments
เป็นกรณีศึกษาที่ดี แต่สงสัยว่าเค้าจะแก้ยังไงต่อ
แล้วตัวแปร array ที่กำหนดตำแหน่งด้วย int จะืำทำยังไงอ่ะครับ
array[int]
http://last0ne.multiply.com
เอ่อ ถ้า array ใหญ่ขนาดนั้น ใส่ในฐานข้อมูลดีกว่าไหม
--
--
หมายถึงค่าที่อาจจะดึงมาจากเดต้าเบสแล้วมันก็ยังเกินน่ะครับ
แบบไม่ได้ใส่ where อะไรเลย ไม่รู้จะมีหรือป่าว
http://last0ne.multiply.com
ประมาณ mysql_fetch_array() รึเปล่าครับ ถ้าข้อมูลเยอะ ๆ ก็ไม่ควรใช้อีกแหละครับหน่วยความจำจะไม่พอเอา
ปกติก็ใช้ mysql_fetch_row() เอา
--
--
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
ผมว่าคุณ 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 ดีกว่าครับ
อ่อ ผม search มาดู อ่านแล้วเมา :-P
ตามคุณ Ford ว่ามาถูกต้องแล้วครับ :-D
--
--
ดีนะไม่ Overflow
คาดการณ์ผิดไปหน่อย
เคยเจอใน RO แล้ว มีคน overflow จนติดลบไปแล้วด้วย
ผมเคยเล่น Transport Tycoon จนเงินติดลบเหมือนกันครับ
เป็นกรณีที่น่าสนใจอืม ^^":
100 ทองแดง = 1 เงิน, 100 เงิน = 1 ทอง, 10000 ทองแดง = 1 ทอง นะครับ
(from gamemun.com/wow)
ทำไมใช้ signed integer
ปัญหา 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 ก็เช่นกันครับ
ถ้าเป็น C++ ก็ทำ class Money มาเลย attribute ก็เป็น list ของ int ถ้า int เต็มก็เพิ่ม int ใน list ซะ แล้ว overload operator เครื่องหมายบวก ลบ คูณ หารเลยได้หรือป่าวครับ (ไม่ได้เขียนนาน ลืมแล้ว >_<) ประมาณว่า
class Money { public: int listInt[100]; Money operator +(Money val) { ... } }
จำได้ว่าขนาด userid ของโปรแกรมที่ผมทำส่วนใหญ่ยังเป็น mediumint อยู่เลย ..
เพราะไม่คิดว่าคนจะเล่นเยอะ 555+
บล็อกของผม: http://sikachu.com
บล็อกของผม: http://sikachu.com
ผมว่ามันเป็นปกติของโปรแกรมเมอร์นะที่จะคิดว่าใช้ตัวแปรแบบนี้ก็น่าจะเพียงพอสำหรับงานที่เราทำอยู่แล้ว ช่วยประหยัด byte ลงไปด้วย จะเผื่อมากไปก็สิ้นเปลืองโดยใช้เหตุ แต่อย่างว่าแหละครับ "ความแน่นอน ก็คือความไม่แน่นอน"
เอ แล้วตัวแปรประเภท byte ของผมมันจะ overflow ไหมหว่า ^_^"
comment no. #40749 แล้ว.... คงอีกนานกว่าจะ overflow
Patrickz's blog | blog @ G2K | blog @ narisa | AsteriskThailand
Patrickz's blog|
linkedin
ผมว่า ง่ายที่สุด เพิ่มหน่วยเงิน อีกอันหนึ่งสิ เป็น มี ทองแดง, เงิน, ทอง แล้วเอาเป็น เพชร
น่าจะง่ายกว่า
It's my life. Open your mind for the future.