เกมที่ไม่ได้ใช้งานจัดการกับจำนวนที่มากเช่นนี้ได้อย่างไร


31

แค่สงสัยว่าเกมเช่น Tap titans และ Cookie Clicker จัดการกับจำนวนที่มากขนาดนี้ได้อย่างไร

ฉันกำลังพยายามใช้งานเกมที่ไม่ได้ใช้งาน แต่รูปแบบตัวเลขที่ใหญ่ที่สุดที่รองรับโดย C # คือทศนิยม

ฉันต้องการสนับสนุนมากถึง 10 ^ 500; ที่จะต้องมีจุดลอย

ฉันจะจัดการสิ่งนี้ได้อย่างไร

PS จะต้องเป็นแพลตฟอร์มข้ามเช่นพีซี, Mac, iOS, Android และเข้ากันได้กับ Unity


2
ถ้าฉันจำได้อย่างถูกต้องคุณสามารถเข้าถึงรหัสของ Cookie Clicker ดังนั้นคุณสามารถตรวจสอบได้ว่า ...
Vaillancourt

ไม่ฉันปิดกั้น Cookie Clicker จากใจแล้ว!
Arturo Torres Sánchez

2
ฉันดูที่แหล่งข้อมูลที่ถอดรหัสแล้วสำหรับเกม TimeClickers Unity doubleพวกเขาเพียงแค่ใช้ หากได้รับฉันฉันจะได้ใช้BigIntegerแม้ว่า
BlueRaja - Danny Pflughoeft

1
@VioletGiraffe: ฉันเห็นด้วยและฉันต้องการที่จะทำให้ฉัน (ของเรา) สงสัยเป็นรูปธรรม (เพื่อช่วยให้ OP ทำให้คำถามชัดเจนขึ้น): อะไรคือ "เกมว่าง" ที่เกี่ยวกับคำถาม (นั่นทำให้แบบนี้ ของเกมกรณีพิเศษสำหรับคนจำนวนมาก)? สิ่งที่ชนิดของตัวเลขคือ " ดังกล่าวเป็นจำนวนมาก" (ไฮไลท์ด้วยตัวเอง) หมายถึง? วิธีการขนาดใหญ่ที่คุณต้องการตัวเลขจะเป็น?
หรือผู้ทำแผนที่

คุณสามารถจัดเก็บจำนวนมากเช่นนี้ในสตริงและใช้ฟังก์ชันเพื่อทำการรวมกับสตริงได้อย่างง่ายดาย
dev-masih

คำตอบ:


40

หากคุณต้องการเก็บจำนวนมหาศาลโดยไม่มีความแม่นยำอย่างสมบูรณ์ตัวอย่างเช่นถ้าคุณแสดง 12,567,000,000,000 เป็น 12.567T (ล้านล้าน) คุณสามารถใช้ค่าทศนิยม / ทศนิยมมาตรฐานและแสดงตัวเลขสำคัญx ตัวแรกด้วยคำต่อท้ายที่เหมาะสม อย่างนี้. เมื่อคุณอยู่ในช่วง octillions คุณจำเป็นต้องสนใจการเพิ่มจำนวนเต็มของแต่ละคนหรือไม่?


4
นี่อาจเป็นคำตอบที่สมเหตุสมผลที่สุดและฉันค่อนข้างแน่ใจว่า Cookie Clicker ใช้โฟลทมาตรฐานในจาวาสคริปต์ - ตรงประเด็นเมื่อฉัน "แฮ็ค" มัน (อ่าน: messed กับคอนโซล) และเมื่อตัวเลขมาถึง 1e308 มันก็กระโดด ถึง "Infinity" และฉันสามารถทำการซื้ออะไรก็ได้ที่ฉันต้องการ XD
Niet the Dark Absolute

1
ที่ดี! ความจริงที่ว่าข้อความกระโดดไปที่ "ไม่มีที่สิ้นสุด" รู้สึกเหมือนนักพัฒนาได้รับการเข้ารหัสป้องกันรอบเหตุการณ์นี้เช่นกัน ความเรียบง่ายคือราชา
Ross Taylor-Turner

19
@RossTurner - อาจจะไม่มีการเข้ารหัสที่เกี่ยวข้องกับการให้มันแสดงข้อความ "Infinity" - ค่าอินฟินิตี้เป็นเพียงลอยได้และจาวาสคริปต์รู้วิธีการแสดงเช่นเดียวกับภาษาอื่น ๆ ทำ
Jibb Smart

มาตรฐานแบบลอยตัว (ความแม่นยำสองเท่า, 8 ไบต์) จะไม่อนุญาตให้แสดงตัวเลขได้สูงสุด 10 ^ 500 ตามที่คำถามดั้งเดิมต้องการนั้นจะขึ้นอยู่กับ ~ 10 ^ 300 หากยังไม่เพียงพอเราควรใช้ความแม่นยำสี่ระดับซึ่งอาจไม่สำคัญขึ้นอยู่กับภาษา
Peteris

1
สิ่งที่โปรแกรมเมอร์ทุกคนควรรู้เกี่ยวกับตัวเลขจุดลอยตัว
Steve

20

คุณสามารถใช้บางอย่างเช่นBigIntegerซึ่งมีเฉพาะใน. net 4.0 หากฉันไม่เข้าใจผิด (ไม่รองรับแพลตฟอร์มการสร้างแบบเอกภาพทั้งหมด)

มีบางไลบรารีที่พยายามใช้ฟังก์ชันนี้โดยไม่ต้องมี. net4.0 ยกตัวอย่างเช่นที่นี่

หรือคุณสามารถใช้ตัวเลขที่น้อยลงเพื่อแสดงค่าที่ใหญ่กว่าโดยการติดตามตัวคูณ ตัวอย่างเช่น:

double value = 9;
enum Multiplier {
   Hundred,
   Thousand,
   Million,
   Billion,
   Trillion
}

ตอนนี้แม้ว่าคุณจะมีค่าเท่ากับ 9 ถ้าคุณจับคู่มันกับตัวคูณของคุณคุณสามารถแทน 9 ได้อย่างมีประสิทธิภาพเป็น 9 ล้านล้าน (โดยการใส่ "trillion" หรือเขียนอะไรบางอย่างที่จะเพิ่มค่าศูนย์ท้ายค่าของคุณ )


เป็นที่น่าสังเกตว่าคลาสเช่นBigIntegerใช้ String หรือ Byte [] แทนจำนวน - ดังนั้นเอฟเฟกต์หนึ่งสามารถสร้างคลาสของตัวเองซึ่งเพิ่งเพิ่มและลบสอง "ตัวเลขเป็น Strings หรือ Bytes" - ( โดยปกติแล้วเกมประเภทนี้จะไม่ ไม่จำเป็นต้องใช้ แต่คุณสามารถรองรับการคูณหรือการหารหรือฟังก์ชั่นขั้นสูงอื่น ๆ ได้เช่นกัน ) - แต่พวกเขาจะต้องจำไว้ว่ามีข้อ จำกัด ทางกายภาพที่หน่วยความจำอาจหมด
DoubleDouble

1
แต่ละไบต์คูณขนาดของตัวเลขของคุณด้วย 256 หากหน่วยความจำของคุณเต็มไปด้วยความพยายามที่จะใช้แทนจำนวนตัวเลขของคุณก็ไม่มีคุณค่าที่แท้จริง 256 ^ (2 billion) = 2 ^ 8 ^ (2 billion) = 2 ^ (16 billion) ~ = 10 ^ (5 billion) (wolframalpha ยากจนที่พยายามทำให้เกิดการแปลงครั้งสุดท้าย) คุณสามารถระบุปริมาตรพลังค์แต่ละอันในจักรวาลที่สังเกตได้โดยใช้ตัวเลข 150 หลัก (<500 บิต)
MichaelS

11

คุณอาจจะต้องเขียนคลาสของคุณเองเพื่อใช้ใน Unity แต่มันจะไม่ยากโดยเฉพาะ

ภายในอาจเป็นรายการจำนวนเต็ม (เช่น a List<int>) โดยแต่ละองค์ประกอบในรายการที่สอดคล้องกับกลุ่มตัวเลข 9 หลัก จำนวนเต็มแต่ละค่าจะมีช่วงตั้งแต่ 0 ถึง 999 999 999 จำนวนเต็มสามารถรองรับได้มากกว่า 2 พันล้านนิดหน่อยและเพิ่มเป็นสองเท่าถ้าไม่ได้ลงนาม แต่คุณจะต้องมีจำนวนมากเกิน "หลัก" 1 000 000 000เพราะคุณต้องการ เพื่อให้สามารถแปลงตัวเลขขนาดใหญ่ของคุณเป็นสตริงเพื่อแสดงผลได้อย่างง่ายดาย มันง่ายกว่าที่จะต่อกันว่ามีทศนิยมอะไรบ้าง ( return group[i].ToString() + group[i-1].ToString() and so on) กว่าจะหาวิธีแสดงผลรวมของกลุ่มที่อยู่นอกช่วงของชนิดข้อมูลปกติใด ๆ

ดังนั้น int แรกในรายการของคุณจะแทน 1s ถัดไปจะเป็นจำนวนพันล้าน ถัดไปจำนวน quadrillions และอื่น ๆ

การเพิ่มและการลบจะทำงานเหมือนกับการเพิ่มและการลบด้วยปากกาและกระดาษซึ่งคุณต้องคอยดูล้นและนำไปสู่ ​​"หลัก" ถัดไป แต่แทนที่จะเป็นตัวเลขที่มีช่วง 0-9 ตัวเลขของคุณอยู่ในช่วงตั้งแต่ 0 ถึง 999 999 999


10

สำหรับการจัดการตัวเลขใหญ่ผมมองสิ่งที่ผมคิดว่าเป็นตัวอย่างที่ดีเหมือนหอคอยฮีโร่ มุมบนซ้าย:

1

2
(ที่มา: mzstatic.com )

วิธีที่จัดการกับตัวเลขนั้นค่อนข้างง่าย: คุณเห็นตัวเลขสองถัง เมื่อคุณได้รับสูงขึ้นในหอคอยและสร้าง "ทองคำ" ให้มากขึ้นถังทั้งสองก็แสดงตัวเลขที่มากขึ้น

120 
120M320K - 120 Million
120B631M - 120 Billion
120T134B - 120 Trillion

เมื่อเกมผ่าน T มันจะย้ายไปที่ a, b, c ... z, aa, ab, ...

56aa608z

ด้วยวิธีนี้มันยังช่วยให้คุณรู้ว่าคุณได้รับทองคำเท่าไรในขณะที่ยังไม่ตีรายละเอียดของเกม

คุณสนใจล้าน ๆ ครั้งหรือไม่เมื่อคุณมีจำนวนล้านล้านผ่านมา?

มันเก็บตัวเลขใน Int, Big Int, Float, Double, Decimal, ... หรือไม่ อาร์เรย์ที่กำหนดเอง? เมื่อคุณจัดการกับตัวเลขในลักษณะ "คลุมเครือ" ฉันไม่คิดว่ามันจะสำคัญ ...

ทั้งหมดที่น่าจะเป็นประเด็นสำคัญที่สุด - ในกรณีนี้ 6 คนแรก ... หลังจากนั้น MAYBE 3 หรือ 6 ถัดไป - เนื่องจากการหารายได้ไม่กี่ร้อย K สามารถเกลือกกลิ้งเป็นล้าน - แต่มีจุดที่ได้รับ ไม่กี่ร้อย K จะไม่ส่งผลกระทบต่อคุณเมื่อคุณกดปุ่ม ... น้อยกว่าและมากกว่า

ระยะของคุณจะแตกต่างกันไป (ขึ้นอยู่กับสิ่งที่คุณต้องการ / ต้องการ) ... แค่คิดว่าฉันจะเอา 2c ของฉันไปใช้กับสิ่งที่ฉันคิดว่าเป็นตัวอย่างที่ดี / ง่าย

แก้ไข:

คิดเพิ่มเติมเกี่ยวกับวิธีที่ฉันจะใช้ระบบหมายเลข: ฉันต้องการหมายเลขที่มี 3 ส่วนสำคัญ: XXXX.YYY (... ) xZZZ

X is the most significant digits, 
Y trailing 
Z the multiplier (multiple of 3).

ดังนั้น 120.365x1 จะเป็น 120k365 ... 120.365x2 จะเป็น 120M365K ... ฯลฯ กด 4 นำหน้า (1200.365x2) แล้วหมุนตัวเลข 1.200365 (... ) x3 ปัง คุณมี 1B200M

XY จะพอดีได้อย่างง่ายดายในทศนิยมหรือลอย ... โดยมี Z อยู่ข้างๆมันเป็น int / ไม่ได้ลงนาม

ด้วยการลอยคุณจะสามารถรักษาจำนวนขนาดใหญ่ แต่ไม่สำคัญมากขึ้นตามจำนวนหลักหลังจุด

Z เป็นตัวแทนของกลุ่มตัวเลขที่เข้าใจง่าย:

K = 1
M = 2
B = 3
T = 4
a = 5 
...
z = 31 (I may be off on this)
aa = 32
...
az = 58
ba = 59
...
...

1

และวิธีง่าย ๆ ในการจัดการกับตัวเลขขนาดใหญ่ก็คือการมีค่า INTEGER มากกว่าหนึ่งค่าจากนั้นดำเนินการล้นใด ๆ หากคุณมีค่า INT แบบ 16 บิต (0 ถึง 65535) และคุณต้องการมากกว่านั้นให้ใช้ค่าแบบ 16 บิตสองค่าในแถว คิดว่ามันเหมือนมีค่า BYTE (0 ถึง 255) แต่ใช้มันได้ถึง 99 หลักของค่า เมื่อมันไปถึง 100 ให้หมุนไปที่ค่า BYTE ที่สูงขึ้นถัดไปสำหรับตัวเลขให้มากที่สุดตามที่คุณเห็นว่ามีประโยชน์ ด้วยคอมพิวเตอร์ GHZ วันนี้แม้แต่การเขียนโค้ดที่เลอะเทอะอย่างนั้นก็ใช้ได้

แน่นอนว่ามีทางเลือกอื่นซึ่งเร็วกว่าเล็กน้อย
หากคุณเพิ่มจำนวน 18 ซ้ำไปซ้ำ ๆ มันจะเร็วกว่าที่จะลบ 2 และเพิ่ม 20 18, 36, 54, 72, 90, 108, ... 18 = 20 + (- 2)
มันทำงานใน Binary ด้วย (ค่าทศนิยมเหมือนกันใน Binary) 10010, 100100, 110110, 1001000
DEC (18) = BIN (10010)
ยกเว้นการแยกวิเคราะห์ไบนารีที่ง่ายขึ้นคุณต้องคิดถึง 18 = 16 + 2
DEC (16 + 2) = BIN (10000 + 00010) หากค่าเท่ากับ 15 ให้คิดว่าเป็นการเพิ่ม 16 ในไบนารีและลบ 1 (10,000-00001)

ด้วยวิธีนี้คุณสามารถเก็บจำนวนชิ้นไว้ที่ขีด จำกัด ที่จัดการได้ต่อมูลค่า
หากคุณกำลังใช้วิธีการเข้ารหัสเลอะเทอะในการ จำกัด ค่า INT พื้นฐาน 16 บิต (0 ถึง 65535) ถึงขีด จำกัด ทศนิยม 4 หลัก (0 ถึง 9999) สิ่งที่คุณต้องทำคือเมื่อค่าเกินขีด จำกัด 9999 ลบ 9999 จากนั้นและนำไปยังค่าถัดไป (เนื่องจากคุณกำลังทำโดยทั่วไป "เพิ่ม & ส่วนย่อย" ด้วยตัวเลขเมื่อเทียบกับการคำนวณไบนารีจริง)

เป็นการดีที่คุณจะใช้ SYMBOLIC MATH ที่คุณได้เรียนในชั้นประถม มันทำงานอย่างไร หากคุณมีสัญลักษณ์ทศนิยม 1 และคุณเพิ่มเป็น 1 คุณจะได้รับสัญลักษณ์ทศนิยม 2 เหตุผลที่ฉันเรียกว่าสัญลักษณ์นี้คือคุณสามารถใช้ชุดสัญลักษณ์ใด ๆ กับตารางการค้นหาของ "IF symbol X (1) ถูกเพิ่มในสัญลักษณ์ X (4) จากนั้นสัญลักษณ์เอาต์พุต X (5) " Symbol X (1) อาจเป็นรูปแมวและสัญลักษณ์ X (4) อาจเป็นสัญญาณ PERCENT แต่มันก็ไม่สำคัญ คุณมีสัญลักษณ์ของคุณกฎพื้นฐานของสิ่งที่เกิดขึ้นจากนั้นสัญลักษณ์เหล่านั้นจะถูกรวมเข้าด้วยกัน (เรียงลำดับเหมือนตารางการคูณที่คุณจำได้ว่าเป็นเด็ก) และสัญลักษณ์ใดที่ต้องส่งผลให้เป็นส่วนหนึ่งของการดำเนินการนั้น ด้วยการใช้ Symbolic Math คุณสามารถเพิ่มจำนวนอนันต์ในขณะที่ไม่เคยเรียกขีด จำกัด ตัวเลขของโปรเซสเซอร์ของคุณ

วิธีการหนึ่งในการเขียนโค้ดอย่างง่าย ๆ คือการมีตัวเลขแต่ละหลักที่คุณต้องการใช้เป็นหน่วยเดียวในอาร์เรย์ขนาดใหญ่ ถ้าคุณต้องการแทนค่าทศนิยม 4096 หลัก (ไม่เกิน 2 หลักต่อหน่วยกล่อง), จากนั้นคุณจัดสรรตำแหน่งอาร์เรย์อาร์เรย์ 4096 ไบต์จำนวน 2 ชุด การจัดเก็บค่าของ 1098874 จะใช้อาร์เรย์เป็น (1) (0) (9) (8) (8) (8) (7) (4) หากคุณเพิ่มมูลค่า 7756 ลงไปคุณจะแปลงเป็น (7) (7) (5) (5) (6) แล้วเพิ่ม ผลลัพธ์จะเป็น (1) (0) (9) (15) (15) (12) (10) ซึ่งคุณจะเปลี่ยนการลบจากขวาไปซ้ายจนกว่ากล่องตัวเลขทั้งหมดจะถูกทำให้เป็นมาตรฐาน (0 ถึง 9) ค่าที่ถูกที่สุด (10) จะมี 10 ค่าลบและค่าผลลัพธ์จะเป็นศูนย์ (0) และจะนำค่า (1) ไปยังกล่องซ้ายถัดไปของ (12) เพื่อให้มัน (13) ซึ่งจะมี 10 ลบออกเพื่อให้เป็น (3)


7
-1 สำหรับ YELLING มากเกินไป
D. Thompson

5
เฮ้ @Gridlock ฉันเพิ่งสังเกตเห็นว่าคุณเป็นผู้ใช้ใหม่ - ยินดีต้อนรับ ฉันควรชี้แจงว่า downvote ของฉันไม่ได้ถาวร มันมีจุดประสงค์เพื่อเป็นการวิจารณ์เชิงสร้างสรรค์ มีค่าต่อคำตอบที่คุณให้ไว้และฉันยินดีที่จะเปลี่ยนเป็น upvote เมื่อคุณทำการแก้ไขที่ฉันร้องขอ นอกจากนี้โปรดทราบว่า SE ไม่ใช่ฟอรัม คำตอบที่ดีนั้นไม่ได้ถูกอ่านและลืมไปแล้ว แก้ไขคำตอบของคุณที่นี่ & ช่วยชุมชนและตัวแทนของคุณ ฉันหวังว่าฉันจะไม่ทำให้คุณกลัว อีกครั้งยินดีต้อนรับและฉันหวังว่าคุณจะใช้คำแนะนำของฉัน
Slipp D. Thompson

1
ข้อเสนอแนะอื่น ๆ ที่ฉันจะนำเสนอคือการใช้การจัดรูปแบบ Markdown พื้นฐานแทนที่จะเป็นตัวพิมพ์ใหญ่ การตัดข้อความใน backticks ( `text`text) จะทำให้เป็นระยะห่างแบบโมโนเหมาะสำหรับชิ้นของรหัสชื่อฟังก์ชั่นข้อมูลและอื่น ๆ การตัดข้อความในเครื่องหมายขีดล่างหรือเครื่องหมายดอกจันจะทำให้ตัวเอียง ( _text_หรือ*text*ข้อความ ) และเครื่องหมายขีดล่างหรือดับเบิล เครื่องหมายดอกจันจะทำให้เป็นตัวหนา ( __text__หรือ**text**ข้อความ )
Slipp D. Thompson

0

สิ่งที่คุณทำคือมีหลายตัวแปรรวมกันและจากนั้นคุณสามารถควบคุมการเพิ่มและล้นระหว่างพวกเขาเอง คุณสามารถมีตัวเลขจำนวนเท่าใดก็ได้ รวมจำนวนเต็ม 10,000 32- บิตและคุณมีจำนวน 32,000 บิตถ้านั่นคือสิ่งที่คุณต้องการ ไม่มีขีด จำกัด ในภาษาการเขียนโปรแกรมใด ๆ ข้อ จำกัด เพียงอย่างเดียวคือสิ่งที่คุณสามารถเข้าใจได้


สำหรับคนที่ให้คะแนนโหวตคุณช่วยอธิบายได้ไหม แม้ว่านี้ไม่ได้เป็นวิธีการแก้ปัญหาที่เป็นที่นิยมหรือคนที่ต้องเป็นศูนย์ความพยายามก็ยังคงเป็นวิธีการแก้ปัญหาและการหนึ่งที่สามารถช่วยให้คุณทำแม้เดียวกันในภาษา / แพลตฟอร์มที่ไม่สนับสนุนหรือdouble BigInteger
TomTsagk
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.