เหตุใดจึงมีตัวเลขหลายประเภท (บิต, int, float, double, long)


9

ฉันได้เรียนรู้ PHP, Java, และ C ตอนนี้ฉันอยากรู้ว่าทำไมมีชนิดข้อมูลตัวเลขมากมายเช่นบิต, int, float, double และ long ทำไมไม่สร้างตัวเลขเพียงประเภทเดียว?

มีประโยชน์กับเรื่องนี้หรือไม่? บางทีถ้าเราใช้จำนวนเต็มเพื่อเก็บจำนวนน้อยเช่นนี้เราสามารถบันทึกความทรงจำได้?


6
นอกเหนือจากคำตอบของ HorusKol: ประเภท 'float' และ 'จำนวนเต็ม' นั้นแตกต่างกันโดยสิ้นเชิง ทุ่นลอยสามารถเก็บตัวเลขได้มาก แต่เมื่อขนาดเพิ่มขึ้นความแม่นยำจะลดลง ความไม่แน่นอนนี้เป็นเพราะวิธีการจัดเก็บลอย ในทางตรงกันข้ามช่วงของค่าที่คุณสามารถจัดเก็บในจำนวนเต็มค่อนข้าง จำกัด แต่ค่านั้นแน่นอนเสมอดังนั้นคุณจึงสามารถเปรียบเทียบค่าได้ง่ายกว่ามาก นอกจากนี้ยังมีพฤติกรรมที่แตกต่างกันสองประเภทด้วยการหาร - จำนวนเต็ม 'ตัด' เป็นจำนวนเต็มที่ใกล้ที่สุดโดยอัตโนมัติลอยทำไม่ได้ พฤติกรรมเหล่านี้แต่ละอย่างมีประโยชน์สำหรับสถานการณ์ที่แตกต่างกัน
kampu

Javascript มีพื้นผิวหมายเลขเดียวเท่านั้น
Esailija

@kampu: จริง ๆ แล้วในหลาย ๆ ภาษาจำนวนเต็มสามารถเก็บหมายเลขใด ๆ ตราบเท่าที่หน่วยความจำ (เสมือน) มีขนาดใหญ่พอที่จะเป็นตัวแทนของมัน
Jörg W Mittag

1
@ JörgWMittag: อย่างไรก็ตามผู้ถามอย่างชัดเจนกำลังพูดถึงภาษาคงที่ไม่ใช่ภาษาไดนามิกเช่น Python CPython ใช้จำนวนเต็ม 'ไม่ จำกัด ช่วง' เป็นอาร์เรย์ของ 32 บิต int โดยมีบิตสุดท้ายในแต่ละ int ที่ใช้เพื่อระบุว่ามีบิตมากกว่านี้หรือไม่ นอกจากนี้ยังสามารถจัดเก็บจำนวนเต็มใด ๆทั้งจำนวนเท่านั้น นั่นหมายความว่าการลอยด้วยหน่วยความจำที่ไม่สิ้นสุดสามารถเก็บค่าไว้ในความแม่นยำ (infinity aleph one) ในขณะที่จำนวนเต็มสามารถเก็บค่าได้อย่างแม่นยำเท่านั้น ( infinity aleph zero )
kampu

@kampu: เนื่องจากตัวเลขทั้งหมดจะถูกแสดงด้วยชุดของบิตแม้จะมีพื้นที่จัดเก็บข้อมูลไม่สิ้นสุดจึงจะมีการแมปแบบหนึ่งต่อหนึ่งระหว่างหมายเลขทศนิยมและจำนวนเต็ม ดังนั้นฉันไม่คิดว่า aleph คนหนึ่งถาม
จาก

คำตอบ:


17

มีเหตุผลสองประการที่คุณควรเกี่ยวข้องกับชนิดข้อมูลตัวเลขที่แตกต่างกัน

1. ประหยัดหน่วยความจำ

for(long k=0;k<=10;k++)
{
    //stuff
}

ทำไมต้องใช้เวลานานเมื่อมันสามารถเป็นจำนวนเต็มได้อย่างง่ายดายหรือแม้แต่เป็นไบต์? แน่นอนคุณจะบันทึกหน่วยความจำหลายไบต์ด้วยการทำเช่นนั้น

2. ตัวเลขจุดลอยตัวและตัวเลขจำนวนเต็มจะถูกเก็บไว้ในคอมพิวเตอร์ต่างกัน

สมมติว่าเรามีหมายเลข 22 เก็บไว้ในจำนวนเต็ม คอมพิวเตอร์จัดเก็บหมายเลขนี้ในหน่วยความจำในรูปแบบไบนารีเป็น:

0000 0000 0000 0000 0000 0000 0001 0110

หากคุณไม่คุ้นเคยกับระบบเลขฐานสองคุณสามารถแสดงสัญลักษณ์ทางวิทยาศาสตร์ได้เป็น: 2 ^ 0 * 0 + 2 ^ 1 * 1 + 2 ^ 2 * 1 + 2 ^ 3 * 0 + 2 ^ 4 * 1 + 2 ^ 5 * 0 + ... + 2 ^ 30 * 0 บิตสุดท้ายอาจใช้หรือไม่ใช้เพื่อระบุว่าจำนวนเป็นลบหรือไม่ (ขึ้นอยู่กับประเภทของข้อมูลที่ลงชื่อหรือไม่ได้ลงชื่อ)

โดยพื้นฐานแล้วมันเป็นเพียงผลรวมของค่า 2 ^ (บิต) *

การเปลี่ยนแปลงนี้จะเกิดขึ้นเมื่อคุณอ้างถึงค่าที่เกี่ยวข้องกับจุดทศนิยม สมมติว่าคุณมีตัวเลข 3.75 เป็นทศนิยม สิ่งนี้เรียกว่า 11.11 ในไบนารี เราสามารถแสดงสิ่งนี้เป็นสัญลักษณ์ทางวิทยาศาสตร์ได้ว่าเป็น 2 ^ 1 * 1 + 2 ^ 0 * 1 + 2 ^ -1 * 1 + 2 ^ -2 * 1 หรือนัยเป็นมาตรฐานที่ 1.111 * 2 ^ 2

คอมพิวเตอร์ไม่สามารถเก็บสิ่งนั้นได้: มันไม่มีวิธีที่ชัดเจนในการแสดงจุดไบนารีนั้น (เวอร์ชันระบบเลขฐานสองของจุดทศนิยม) คอมพิวเตอร์สามารถจัดเก็บ 1 และ 0 เท่านั้น นี่คือที่มาชนิดข้อมูลจุดลอยเข้ามา

สมมติว่า sizeof (float) เท่ากับ 4 ไบต์จากนั้นคุณมีทั้งหมด 32 บิต บิตแรกถูกกำหนดให้ "sign bit" ไม่มีลอยหรือคู่ที่ไม่ได้ลงชื่อ 8 บิตถัดไปใช้สำหรับ "เลขชี้กำลัง" และ 23 บิตสุดท้ายถูกใช้เป็น "ซิกนิฟิแคนด์" (หรือบางครั้งเรียกว่า mantissa) ใช้ตัวอย่าง 3.75 ของเราเลขชี้กำลังของเราจะเท่ากับ 2 ^ 1 และซิกนิฟิแคนด์ของเราคือ 1.111

ถ้าบิตแรกคือ 1 จำนวนจะเป็นลบ ถ้าไม่เป็นบวก เลขชี้กำลังถูกแก้ไขโดยบางสิ่งที่เรียกว่า "ความลำเอียง" ดังนั้นเราจึงไม่สามารถเก็บ "0000 0010" เป็นเลขชี้กำลัง อคติสำหรับตัวเลขทศนิยมที่มีความแม่นยำเดียวคือ 127 และอคติสำหรับความแม่นยำสองเท่า (นี่คือที่ประเภทข้อมูลสองครั้งได้รับชื่อ) คือ 1023 23 บิตสุดท้ายจะถูกสงวนไว้สำหรับซิกนิฟิแคนด์ นัยสำคัญเป็นเพียงค่าของ RIGHT ของจุดไบนารี่ของเรา

เลขชี้กำลังของเราคืออคติ (127) + เลขชี้กำลัง (1) หรือแทนด้วยเลขฐานสอง

1000 0000

ความสำคัญของเราคือ:

111 0000 0000 0000 0000 0000

ดังนั้น 3.75 จึงแสดงเป็น:

0100 0000 0111 0000 0000 0000 0000 0000

ทีนี้เรามาดูตัวเลข 8 ที่แสดงเป็นเลขทศนิยมและเลขจำนวนเต็ม:

0100 0001 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 1000

คอมพิวเตอร์จะเพิ่ม 8.0 และ 8 ได้อย่างไรในโลก หรือเพิ่มทวีคูณ! คอมพิวเตอร์ (โดยเฉพาะอย่างยิ่งคอมพิวเตอร์ x86) มีส่วนต่าง ๆ ของ CPU ที่เพิ่มหมายเลขทศนิยมและจำนวนเต็ม


3
3) แม้ว่าจะไม่ค่อยมีปัญหา: การทำงานกับตัวเลขที่ใหญ่กว่าคำพูดของคอมพิวเตอร์ช้าลง
Loren Pechtel

6

ย้อนกลับก่อนที่เราจะมีระบบกิกะไบต์ (หรือในระบบฝังตัวที่ทันสมัยเช่น Arduino) หน่วยความจำอยู่ที่ระดับพรีเมียมและมีการใช้วิธีการจดชวเลขเพื่อระบุจำนวนหน่วยความจำที่จะใช้มากขึ้น - BIT นั้นตรงไปตรงมา ของหน่วยความจำ

ขนาดและชื่อข้อมูลอื่น ๆ จะแตกต่างกันไปตามระบบ บนระบบ 32- บิตโดยทั่วไป INT (หรือ MEDIUMINT) จะเป็น 2 ไบต์โดยทั่วไป LONGINT จะเป็น 4 ไบต์และ SMALLINT จะเป็นไบต์เดียว ระบบ 64 บิตสามารถตั้งค่า LONGINT เป็น 8 ไบต์

แม้ตอนนี้ - โดยเฉพาะอย่างยิ่งในแอปพลิเคชันฐานข้อมูลหรือโปรแกรมที่มีหลายอินสแตนซ์ที่ทำงานบนเซิร์ฟเวอร์ (เช่นสคริปต์ด้านเซิร์ฟเวอร์บนเว็บไซต์) - คุณควรระมัดระวังเกี่ยวกับสิ่งที่คุณเลือก การเลือกจำนวนเต็มกว้าง 2, 4 หรือ 8 ไบต์เพื่อเก็บค่าระหว่าง 0 และ 100 (ซึ่งสามารถพอดีในหนึ่งไบต์) จะสิ้นเปลืองอย่างไม่น่าเชื่อถ้าคุณมีตารางฐานข้อมูลที่มีระเบียนนับล้าน

ข้อมูลเพิ่มเติม: https://en.wikipedia.org/wiki/Integer_(computer_science)


คำตอบที่ดี +1
Vinay

7
ไม่เพียง 'ย้อนกลับไปก่อน' แต่ยัง 'ตอนนี้เมื่อระบบมีขนาดเล็ก' บนอุปกรณ์ขนาดของ Arduino หนึ่งจะต้องประหยัด
9000

1
ระบบใดที่ใช้เพียง 1 บิตในการจัดเก็บบิต บิตมักไม่สามารถระบุแอดเดรสได้โดยตรง
jk

1
มันเป็นความจริงในสถาปัตยกรรมจำนวนมาก - แต่บิตสามารถระบุตำแหน่งได้โดยตรงในระบบเก่าจริง ๆ และแม้แต่ระบบฝังตัวล่าสุดบางตัว (คอนโทรลเลอร์บางตัวที่ฉันตั้งโปรแกรมเมื่อ 10 ปีที่แล้วทำงานกับบิต - บิตเหล่านั้นมีตำแหน่งความกว้าง ทุกวันนี้ฉันคิดว่าคอมไพเลอร์ทำงานออกมาและวางมันลงในไบต์อาร์เรย์
HorusKol

ฉันคิดว่าปัจจัยที่สำคัญคือความสามารถและประสิทธิภาพของ CPU มากกว่าความกังวลของหน่วยความจำ
James

4

นอกจากจุดที่ยอดเยี่ยมของ cpmjr123 เกี่ยวกับความขาดแคลนของหน่วยความจำและความแม่นยำและช่วงปิดการซื้อขายนั้นยังมีการแลกเปลี่ยน CPU

เครื่องจักรที่ทันสมัยส่วนใหญ่มีฮาร์ดแวร์พิเศษสำหรับการดำเนินการจุดลอยตัวที่เรียกว่า FPU นอกจากนี้ยังมีระบบที่ไม่มี FPU (ทุกวันนี้อุปกรณ์เหล่านี้เป็นอุปกรณ์ฝังขนาดเล็ก) ดังนั้นขึ้นอยู่กับฮาร์ดแวร์เป้าหมายของคุณคุณจะต้องไม่ใช้ประเภทจุดลอยเลยหรือใช้ไลบรารี่ของจุดลอยตัวซอฟต์แวร์ แม้ว่าเครื่องของคุณจะมี FPU แต่ก็มีความแตกต่างในอดีตในสิ่งที่ฟังก์ชั่นสามารถใช้งานได้ ฟังก์ชั่นใด ๆ ที่ไม่ได้ทำในฮาร์ดแวร์จะต้องทำในซอฟต์แวร์ (หรือหลีกเลี่ยง)

การคำนวณจุดลอยตัวในซอฟต์แวร์นั้นกระทำโดยการดำเนินการที่ง่ายขึ้นจำนวนมากซึ่งฮาร์ดแวร์รองรับ คุณจะได้รับการแลกเปลี่ยนความเร็วที่อาจเกิดขึ้นเช่นกัน


4

บางทีสิ่งที่สำคัญที่สุดคือมีประเภทตัวเลขพื้นฐานสามแบบ

จำนวนเต็มทศนิยมคงที่และจุดลอย

พวกเขาทั้งหมดทำงานแตกต่างกัน

การดำเนินการอย่างง่ายเช่น 7/2 สามารถให้คำตอบได้ 3, 3.50 และ 3.499 ขึ้นอยู่กับชนิดข้อมูลที่ใช้

"ทศนิยมคงที่" เป็นประเภท Cinderella สนับสนุนเฉพาะภาษาดั้งเดิมในสองสามภาษาเช่น COBOL และ VisualBasic มันมีความสนใจเพียงเล็กน้อยสำหรับนักวิทยาศาสตร์คอมพิวเตอร์ แต่มีความสำคัญสำหรับทุกคนที่ส่งชุดบัญชีหรือคำนวณภาษีการขายในใบแจ้งหนี้


ฉันจะแยกพวกมันออกจากกัน: ตัวเลขไม่ต่อเนื่อง, ตัวเลขโดยประมาณ, และการล้อมวงพีชคณิต ตัวอย่างทั่วไปใน C จะเป็นint, floatและunsigned intตามลำดับ ประเภทจุดคงที่เป็นประเภทย่อยของประเภทแยก แต่แหวนพีชคณิตมีความแตกต่างจากตัวเลข [ต้องสับสนเกี่ยวกับประเภทที่ไม่ได้ลงนามใน C เกิดจากความจริงที่ว่าพวกเขาส่วนใหญ่ทำตัวเหมือนวงแหวนมากกว่าตัวเลข แต่ไม่สอดคล้องกันมาก] .
supercat

3

พวกเขาได้ประโยชน์อะไรบ้าง?

แน่นอน. มีประโยชน์มากมาย ในโลกของหน่วยความจำคอมพิวเตอร์เป็นสิ่งสำคัญที่สุดที่ต้องพิจารณา อะไรคือการใช้หน่วยความจำ 2kb เมื่อข้อมูลสามารถพอดีในน้อยกว่า 1kb? . การเพิ่มประสิทธิภาพควรจะมี หากคุณใช้หน่วยความจำมากขึ้นจะทำให้คอมพิวเตอร์ของคุณเร็วขึ้นอย่างเห็นได้ชัด คุณชอบที่จะมีมันจริงเหรอ? ไม่มีสิทธิ์...?

int - 2 bytes (16 bits)

long - 4 bytes (32 bits)

long long - 8 bytes (64 bits)

float - 4 bytes

ไม่เพียง แต่หน่วยความจำเท่านั้น แต่ยังมีการจัดประเภทของตัวเลขอีกด้วย สำหรับจุดลอยตัวอินสแตนซ์ ความแม่นยำมีความสำคัญอย่างมากและแน่นอนว่าเราควรมีประเภทเดียวที่สามารถให้ความแม่นยำกับเราได้มากกว่า

หากเราพิจารณาวันสมัยก่อนเรามีความทรงจำน้อยลงอย่างที่คุณอาจรู้ เพื่อประหยัดและใช้มันอย่างชาญฉลาดเรามีความแตกต่างเหล่านี้ และอื่น ๆ อีกมากมายถ้าคุณเพียงแค่ไปข้างหน้าและลองค้นหาด้วย google หวังว่านี่จะช่วยได้


3

จำนวนเต็มและจำนวนจริง (จำนวนลอย, สองเท่า) เป็นประเภทที่แตกต่างกันตามแนวคิดที่มีชุดของการดำเนินการที่แตกต่างกันและคุณสมบัติที่แท้จริง

จำนวนเต็มนับได้ แต่ไม่ลอยเป็นต้น

ความจริงแล้ว Float / double number เป็นโครงสร้างที่รวมสองฟิลด์จำนวนเต็ม: mantissa และ exponent จำนวนเชิงซ้อน (ที่คุณแยกออกจากการพิจารณา) มีความซับซ้อนมากยิ่งขึ้น

ภาษาในทางปฏิบัติใด ๆ ควรมีจำนวนเต็มอย่างน้อยและลอยตัวเป็นประเภทที่แตกต่างกัน - การดำเนินการที่แตกต่างกันเกินไปกับพวกเขา


ฉันไม่คุ้นเคยกับ "ตัวเลขที่ซับซ้อน" ที่คุณพูดถึง คุณอธิบายเพิ่มเติมได้ไหม
cpmjr123

ตรวจสอบสิ่งนี้: en.wikipedia.org/wiki/Complex_number
c-smile

ฉันตระหนักถึงตัวเลขที่ซับซ้อนในรูปแบบของ + bi ฉันขอข้อมูลเพิ่มเติมเกี่ยวกับวิธีที่คอมพิวเตอร์เก็บหมายเลขที่ซับซ้อน สำหรับความรู้ของฉันไม่มีประเภทข้อมูลดั้งเดิมที่สนับสนุนสิ่งนี้
cpmjr123

จำนวนเชิงซ้อนจะถูกเก็บไว้เป็นค่าทศนิยมสองค่าคือa(ส่วนจริง) และb(ส่วนจินตภาพ) โดยทั่วไปแล้วซีพียูจะไม่ใช้การสนับสนุนดั้งเดิมสำหรับการดำเนินการกับจำนวนเชิงซ้อนแม้ว่า CPU อาจใช้คำสั่งคูณทวีคูณแบบเร่งสำหรับการดำเนินการกับคู่ของค่าเช่น (a b + c d) และ ( a-b d)

1
นอกจากนี้หลายภาษามีบางประเภทที่พฤติกรรมส่วนใหญ่ถูกกำหนดว่าเป็นแหวนพีชคณิตการพัน (เช่นหากตัวแปรประเภทuint16_tถือ 65535 การเพิ่มขึ้นจะทำให้เป็น 0) ตามหลักการแล้วภาษาจะมีประเภทที่แยกจากกันอย่างหมดจดสำหรับการแสดงวงแหวนและตัวเลขเกี่ยวกับพีชคณิตการพัน (อนุญาตตัวเลขที่ล้นไปติดอยู่ในขณะที่อนุญาตให้ใช้โค้ดเพื่อดำเนินการกับสิ่งที่คาดว่าจะห่อได้ง่าย)
supercat

-1

นอกจากนี้ความจริงที่ว่าชนิดจุดลอยตัวนั้นมีความแตกต่างอย่างสิ้นเชิงจากประเภทจำนวนเต็มฉันต้องการยกตัวอย่างให้มากขึ้นว่าทำไมขนาดต่อจำนวนนั้นสำคัญจริงๆ

ลองนึกภาพคุณต้องการเรียงลำดับ (ยาว) อาร์เรย์ ตัวอย่างเช่นใน C:

int numbers[100000000];

ดังนั้นที่นี่เรามี 100 ล้านตัวเลข

หากแต่ละหมายเลขมีความยาวเพียงหนึ่งไบต์ (ดังนั้นควรใช้unsigned charแทนint) ดังนั้นต้องใช้พื้นที่ 100 ล้านไบต์

ถ้าคุณใช้doubleนี่ก็มักจะเป็น 8 ไบต์ต่อหมายเลขดังนั้น 800 ล้านไบต์ของพื้นที่

ดังนั้นทุกครั้งที่คุณทำงานกับวัตถุจำนวนมาก (ตัวเลขในตัวอย่างนี้) ขนาดต่อวัตถุ (ขนาดต่อจำนวนในตัวอย่างนี้) มีความสำคัญจริงๆ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.