เป็นไปได้ไหมที่จะแยกความแตกต่างระหว่าง 0 ถึง -0


94

ฉันรู้ว่าค่าจำนวนเต็ม0และ-0เป็นหลักเหมือนกัน แต่ฉันสงสัยว่าเป็นไปได้ไหมที่จะแยกความแตกต่างระหว่างพวกเขา

ตัวอย่างเช่นฉันจะทราบว่าตัวแปรที่ได้รับมอบหมาย-0?

bool IsNegative(int num)
{
    // How ?
}

int num = -0;
int additinon = 5;

num += (IsNegative(num)) ? -addition : addition;

ค่าที่-0บันทึกไว้ในหน่วยความจำเป็นวิธีเดียวกับ0หรือไม่


9
สำหรับจำนวนเต็มไม่มีความแตกต่าง
Maroun

14
สิ่งนี้ขึ้นอยู่กับการนำไปใช้งาน แต่สำหรับการนำไปใช้งานที่intแสดงในส่วนเสริมของ 2 (โดยส่วนใหญ่ที่พบบ่อยที่สุด) 0และ-0มีการแทนค่าบิตเหมือนกัน
Mankarse

11
บนเครื่องเสริมของ 2 ไม่มีความแตกต่างในระดับบิต
Marco A.

17
@VirtualSnake: "ในไบนารี" หมายถึงอะไร? นอกจากนี้ในความเป็นจริงการเข้ารหัสไบนารีที่มีคือความแตกต่างระหว่าง -0 และ 0 เข้าสู่ระบบและขนาดเช่น
Benjamin Lindley

8
@VirtualSnake intที่เหมาะสมเรากำลังพูดถึง ดูการเข้ารหัสสมบูรณ์คน
CiaPan

คำตอบ:


112

ขึ้นอยู่กับเครื่องที่คุณกำหนดเป้าหมาย

บนเครื่องที่ใช้การแทนค่า 2สำหรับจำนวนเต็มจะไม่มีความแตกต่างที่ระดับบิตระหว่าง0และ-0(มีการแทนค่าเดียวกัน)

หากเครื่องของคุณใช้ส่วนเสริมคุณทำได้แน่นอน

0000 0000   -> signed01111 1111   -> signed0

เห็นได้ชัดว่าเรากำลังพูดถึงการใช้การสนับสนุนแบบเนทีฟโปรเซสเซอร์ x86 ซีรีส์มีการสนับสนุนแบบเนทีฟสำหรับการแสดงหมายเลขที่ลงนามเสริมของทั้งสอง การใช้การแสดงอื่น ๆ เป็นไปได้อย่างแน่นอน แต่อาจมีประสิทธิภาพน้อยกว่าและต้องการคำแนะนำเพิ่มเติม

(ดังที่ JerryCoffin ยังกล่าวไว้: แม้ว่าส่วนเสริมจะได้รับการพิจารณาส่วนใหญ่ด้วยเหตุผลทางประวัติศาสตร์การแสดงขนาดที่ลงนามยังคงเป็นเรื่องธรรมดาและมีการแสดงแยกต่างหากสำหรับศูนย์ลบและบวก)


6
@TobiMcNamobi: ไม่น่าจะเพียงพอที่จะกังวลเกี่ยวกับ ฉันจะแปลกใจถ้ามีใครเคยใส่ใจกับพอร์ตคอมไพเลอร์ C ++ เพื่อสร้างเอาต์พุตสำหรับเครื่องดังกล่าว
Benjamin Lindley

1
ฉันเห็นด้วยกับเบนจามินในอดีตเคยมีเครื่องจักรที่ใช้มัน แต่ปัจจุบันฉันไม่รู้จักเครื่องจักรผลิตที่ใช้มัน อย่างไรก็ตามเป็นสิ่งที่ดีที่ควรทราบและพึงระลึกไว้เสมอ
Marco A.

4
ส่วนเสริมของ @TobiMcNamobi ยังคงใช้อยู่ในระบบ UNISYS 2200 stackoverflow.com/a/12277974/995714 stackoverflow.com/q/6971886/995714
phuclv

2
ผมไม่เคยมองที่ความต้องการส่วนประกอบหนึ่งของ - ไม่มาตรฐานจริงรับประกันว่า0และ-0มีความแตกต่างกัน ? ฉันคาดหวังว่ามันจะทำงานเหมือนการอนุญาตให้ใช้แทนค่าสองบิตที่มีค่าเท่ากันได้มากขึ้นและโปรแกรมของคุณสามารถใช้ค่าใดก็ได้

8
@Hurkly: ไม่แม้ว่าจะมีการแทนค่าศูนย์ลบอยู่ แต่มาตรฐานไม่รับประกันว่าการกำหนดหรือการเริ่มต้นโดยใช้นิพจน์-0กล่าวคือผลลัพธ์ของการใช้ตัวดำเนิน-การยูนารีกับค่าคงที่จำนวนเต็ม0เป็นการแทนค่าศูนย์ที่เป็นลบ โดยไม่คำนึงถึงการเป็นตัวแทนมาตรฐานไม่เคยพูด0และ-0เป็นค่าที่แตกต่างกันทางคณิตศาสตร์เพียงแต่ว่าอาจมีรูปแบบบิตลบศูนย์ ถ้ามีก็ยังคงแทนค่าตัวเลขเดิม 0.
Steve Jessop

14

สำหรับint(ในการแทนค่า "2's complement" ที่เกือบจะเป็นสากล) การแทนค่า0และ-0เหมือนกัน (อาจแตกต่างกันสำหรับการแสดงตัวเลขอื่น ๆ เช่นจุดลอยตัว IEEE 754)


9
>> สมมติว่าเป็นตัวแทนของ 2
Marco A.

12

เริ่มต้นด้วยการแสดงส่วนเติมเต็มของ 0 ใน 2 (แน่นอนว่ามีระบบและการแสดงอื่น ๆ อีกมากมายที่นี่ฉันหมายถึงระบบเฉพาะนี้) สมมติว่า 8 บิตศูนย์คือ:

0000 0000

ตอนนี้ให้พลิกบิตทั้งหมดและเพิ่ม 1 เพื่อรับส่วนเติมเต็ม 2:

1111 1111 (flip)
0000 0001 (add one)
---------
0000 0000

เราได้0000 0000และนั่นคือตัวแทนของ -0 เช่นกัน

แต่สังเกตว่าในส่วนเติมเต็มของ 1 ลงนาม 0 คือ 0000 0000 แต่ -0 คือ 1111 1111


1
ฉันขอทราบได้ไหมว่าทำไมการโหวตลงคะแนนเพื่อปรับปรุงคำตอบของฉันได้โปรด?
Maroun

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

9

ฉันตัดสินใจที่จะทิ้งคำตอบนี้ไว้เนื่องจากการใช้งาน C และ C ++ มักจะเกี่ยวข้องกันอย่างใกล้ชิด แต่ในความเป็นจริงมันไม่ได้คล้อยตามมาตรฐาน C อย่างที่ฉันคิด ประเด็นยังคงอยู่ที่มาตรฐาน C ++ ไม่ได้ระบุว่าจะเกิดอะไรขึ้นสำหรับกรณีเช่นนี้ นอกจากนี้ยังเกี่ยวข้องด้วยว่าการแสดงที่ไม่ใช่สองส่วนเสริมนั้นหาได้ยากมากในโลกแห่งความเป็นจริงและแม้ว่าจะมีอยู่จริง แต่ก็มักจะซ่อนความแตกต่างไว้ในหลาย ๆ กรณีแทนที่จะเปิดเผยว่าเป็นสิ่งที่ใครบางคนสามารถคาดหวังได้โดยง่าย


พฤติกรรมของศูนย์ลบในการแทนค่าจำนวนเต็มซึ่งมีอยู่นั้นไม่ได้กำหนดไว้อย่างเข้มงวดในมาตรฐาน C ++ เหมือนกับที่อยู่ในมาตรฐาน C อย่างไรก็ตามอ้างถึงมาตรฐาน C (ISO / IEC 9899: 1999) เป็นการอ้างอิงเชิงบรรทัดฐานที่ระดับบนสุด [1.2]

ในมาตรฐาน C [6.2.6.2] ศูนย์ลบสามารถเป็นผลลัพธ์ของการดำเนินการระดับบิตเท่านั้นหรือการดำเนินการที่มีศูนย์ลบอยู่แล้ว (ตัวอย่างเช่นการคูณหรือหารศูนย์ลบด้วยค่าหรือการเพิ่มศูนย์ลบให้กับ ศูนย์) - การใช้ตัวดำเนินการลบยูนารีกับค่าของศูนย์ปกติดังที่แสดงในตัวอย่างของคุณจึงรับประกันได้ว่าจะให้ผลลัพธ์เป็นศูนย์ปกติ

แม้ในกรณีที่สามารถสร้างศูนย์ลบได้ แต่ก็ไม่มีการรับประกันว่าจะทำได้แม้ในระบบที่สนับสนุนค่าลบศูนย์:

ไม่ได้ระบุว่ากรณีเหล่านี้สร้างศูนย์ลบหรือศูนย์ปกติจริงหรือไม่และศูนย์ลบจะกลายเป็นศูนย์ปกติหรือไม่เมื่อเก็บไว้ในวัตถุ

ดังนั้นเราสามารถสรุปได้: ไม่ไม่มีวิธีที่เชื่อถือได้ในการตรวจจับกรณีนี้แม้ว่าจะไม่ใช่เพราะข้อเท็จจริงที่ว่าการแสดงที่ไม่ใช่สองส่วนเสริมเป็นเรื่องผิดปกติในระบบคอมพิวเตอร์สมัยใหม่

ในส่วนของมาตรฐาน C ++ ไม่ได้กล่าวถึงคำว่า "ศูนย์ลบ" และมีการพูดถึงรายละเอียดของขนาดที่เซ็นชื่อและการแสดงส่วนเสริมน้อยมากยกเว้นหมายเหตุ [3.9.1 วรรค 7] ว่าได้รับอนุญาต


โดยทั่วไปไม่ความจริงที่ว่าบางสิ่งเป็นจริง / จำเป็นใน C ไม่จำเป็นต้องหมายความว่าเป็นจริง / จำเป็นใน C ++ ความจริงที่ว่า C เป็นการอ้างอิงเชิงบรรทัดฐานหมายความว่า C ++ หมายถึงมาตรฐาน C สำหรับสิ่งต่างๆ (ส่วนใหญ่เป็นเนื้อหาของส่วนหัวมาตรฐาน) แต่คำจำกัดความของประเภทจำนวนเต็มไม่ใช่หนึ่งในสิ่งเหล่านั้น อย่างไรก็ตามการไม่มีวิธีรับประกันในการสร้างศูนย์ลบหมายความว่าสิ่งที่คุณสรุปยังคงเป็นจริงไม่มีวิธีที่แน่นอนในการสร้างหนึ่งโดยใช้เลขคณิตแม้ว่าจะมีการแทนอยู่ก็ตาม
Steve Jessop

แล้วทำไมมาตรฐาน C ++ ถึงมีรายละเอียดน้อยกว่านี้มาก?
Random832

1
ฉันคิดว่ารสนิยมส่วนตัวถ้าจำนวนคนลงคะแนนในมาตรฐาน C ++ ถือได้ว่าเป็น "ส่วนบุคคล" :-) ถ้ามันจะเลื่อนไปตามมาตรฐาน C สำหรับคำจำกัดความ แต่ก็สามารถทำงานได้อย่างเหมาะสม และไม่มีรายละเอียดเช่นเดียวกับในกรณีอื่น ๆ
Steve Jessop

"C ++ เป็นภาษาโปรแกรมสำหรับวัตถุประสงค์ทั่วไปโดยใช้ภาษาโปรแกรมซีตามที่อธิบายไว้ใน ISO / IEC 9899: 1999 ภาษาโปรแกรม - C (ต่อไปนี้เรียกว่ามาตรฐาน C)" [1.1 para 2] มีความหมายเชิงบรรทัดฐานหรือไม่? ฉันคิดว่าโดยทั่วไปมีจุดประสงค์เพื่อรวมมาตรฐาน C สำหรับสิ่งที่ไม่ได้ถูกแทนที่โดยมาตรฐาน C ++ โดยเฉพาะ
Random832

@ Random832 ไม่เป็นเพียงบันทึกทางประวัติศาสตร์ (ตัวอย่างเช่นไม่มี_Boolหรือ_Complexหรือกำหนด initializers หรือตัวอักษรผสมใน C ++) มาตรฐาน C ++ รู้วิธีรวมมาตรฐาน C เมื่อต้องการเช่น [basic.fundamental] / p3: "ประเภทจำนวนเต็มที่ลงนามและไม่ได้ลงนามจะต้องเป็นไปตามข้อ จำกัด ที่กำหนดในมาตรฐาน C ส่วน 5.2.4.2.1"
TC

8

หากเครื่องของคุณมีการแสดงที่แตกต่างกันสำหรับ-0และ+0จากนั้นmemcmpจะสามารถที่จะแยกพวกเขา

หากมี padding bits จริง ๆ แล้วอาจมีการแสดงหลายค่าสำหรับค่าอื่นที่ไม่ใช่ศูนย์เช่นกัน


5

ในสเปคภาษา C ++ ไม่มี int เช่นลบศูนย์

เพียงคนเดียวที่มีความหมายทั้งสองคำมีความเป็นผู้ประกอบการเอก-นำไปใช้0เช่นเดียวกับสามบวกห้าเป็นเพียงผู้ประกอบการไบนารี+นำไปใช้และ35

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


ในทางตรงกันข้ามจุดลอยตัว (ตาม IEEE) มีศูนย์บวกและลบแยกกัน สามารถแยกแยะได้เช่นเมื่อหาร 1 ด้วยพวกเขา ศูนย์บวกทำให้เกิดอินฟินิตี้ที่เป็นบวก ศูนย์ลบทำให้เกิดอินฟินิตี้เชิงลบ


อย่างไรก็ตามหากมีการแสดงหน่วยความจำที่แตกต่างกันของ int 0 (หรือ int ใด ๆ หรือค่าอื่น ๆ ของประเภทอื่น ๆ ) คุณสามารถใช้memcmpเพื่อค้นหาว่า:

#include <string>

int main() {
    int a = ...
    int b = ...
    if (memcmp(&a, &b, sizeof(int))) {
        // a and b have different representations in memory
    }
}

แน่นอนว่าหากสิ่งนี้เกิดขึ้นนอกการดำเนินการหน่วยความจำโดยตรงค่าทั้งสองจะยังคงทำงานในลักษณะเดียวกัน


3
ที่จริงแล้วภาษาที่ไม่ได้บังคับว่ามีอยู่ไม่ได้หมายความว่าภาษานั้นจะบังคับให้ไม่มี คำแนะนำ: ไม่บังคับ
Deduplicator

2
@Deduplicator เรียงลำดับ. โดย "ในภาษา C ++" ฉันหมายถึง "ในข้อกำหนดภาษา C ++ " เนื่องจากไม่มีการกล่าวถึงตัวกรองน้ำในข้อมูลจำเพาะเช่นกันฉันจึงสามารถพูดได้ว่า "C ++ ไม่มีโฟรบิเนเตอร์" โดยไม่มีความคลุมเครือมากเกินไป ฉันคิดว่ามันชัดเจน แต่ฉันจะปรับปรุงมัน
Paul Draper

1
ข้อมูลจำเพาะของภาษาไม่ได้กล่าวถึงยูนิคอร์นด้วย
ypercubeᵀᴹ

2

เพื่อให้ง่ายขึ้นฉันพบว่ามันง่ายขึ้นในการมองเห็น

ประเภทint (_32) จะถูกเก็บไว้กับ32 บิต 32 บิตหมายความ ^ 32 = 4294967296 2 ค่าที่ไม่ซ้ำกัน ดังนั้น:

ช่วงข้อมูลint ที่ไม่ได้ลงชื่อคือ 0 ถึง 4,294,967,295

ในกรณีที่ค่าติดลบขึ้นอยู่กับวิธีการจัดเก็บ เผื่อ

ในกรณีที่มีค่าส่วนประกอบของ One -0 อยู่


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