Apakah mungkin untuk membedakan antara 0 dan -0?


94

Saya tahu bahwa nilai integer 0dan -0pada dasarnya sama. Tapi, saya bertanya-tanya apakah mungkin untuk membedakan keduanya.

Misalnya, bagaimana saya mengetahui jika suatu variabel telah ditetapkan -0?

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

int num = -0;
int additinon = 5;

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

Apakah nilai yang -0disimpan dalam memori sama persis dengan 0?


9
Untuk bilangan bulat, tidak ada perbedaan.
Maroun

14
Ini bergantung pada implementasinya, tetapi untuk implementasi intyang direpresentasikan dalam komplemen 2 (sejauh ini paling sering ditemui), 0dan -0memiliki representasi bitwise yang identik.
Mankarse

11
Pada mesin pelengkap 2 tidak ada perbedaan pada tingkat bit.
Marco A.

17
@VirtualSnake: Apa artinya "dalam biner"? Ada, pada kenyataannya, pengkodean biner yang ada adalah perbedaan antara -0 dan 0 Masuk dan besarnya, misalnya.
Benjamin Lindley

8
@VirtualSnake Benar, yang sedang kita bicarakan int. Lihat pengkodean komplemen Ones .
CiaPan

Jawaban:


112

Itu tergantung pada mesin yang Anda targetkan.

Pada mesin yang menggunakan representasi komplemen 2 untuk bilangan bulat, tidak ada perbedaan pada tingkat bit antara 0dan -0(keduanya memiliki representasi yang sama)

Jika mesin Anda menggunakan pelengkap , Anda pasti bisa

0000 0000   -> signed0
1111 1111   -> signed   0

Jelas kita berbicara tentang penggunaan dukungan asli , prosesor seri x86 memiliki dukungan asli untuk representasi komplemen dua nomor yang ditandatangani. Menggunakan representasi lain pasti mungkin tetapi mungkin kurang efisien dan membutuhkan lebih banyak instruksi.

(Seperti yang juga dicatat JerryCoffin: bahkan jika komplemen seseorang telah dianggap sebagian besar karena alasan historis, representasi besaran yang ditandatangani masih cukup umum dan memang memiliki representasi terpisah untuk nol negatif dan positif)


6
@TobiMcNamobi: Sepertinya tidak pernah cukup untuk dikhawatirkan. Saya akan terkejut jika ada yang pernah repot-repot mem-port kompiler C ++ untuk menghasilkan keluaran untuk mesin seperti itu.
Benjamin Lindley

1
Saya setuju dengan Benjamin, secara historis telah ada mesin menggunakannya, tapi saat ini saya tidak kebetulan tahu mesin produksi yang menggunakannya. Namun demikian, selalu baik untuk diketahui dan diingat.
Marco A.

4
Pelengkap @TobiMcNamobi seseorang masih digunakan di Unisys 2200 sistem stackoverflow.com/a/12277974/995714 stackoverflow.com/q/6971886/995714
phuclv

2
Saya tidak pernah melihat persyaratan melengkapi seseorang - tidak standar benar-benar jaminan bahwa 0dan -0yang berbeda ? Sejujurnya saya akan mengharapkannya untuk berperilaku lebih seperti mengizinkan representasi dua bit dengan nilai yang sama, dan program Anda dapat menggunakan yang mana pun rasanya.

8
@Hurkly: tidak, meskipun ada representasi nol negatif, standar tidak menjamin bahwa penetapan atau inisialisasi menggunakan ekspresi -0, yaitu hasil penerapan -operator unary ke konstanta integer 0, adalah representasi nol negatif. Terlepas dari representasi, standar tidak pernah mengatakan 0dan -0merupakan nilai yang berbeda secara matematis, hanya saja mungkin ada pola bit negatif-nol. Jika ada, itu masih mewakili nilai numerik yang sama, 0.
Steve Jessop

14

Untuk int(dalam representasi "komplemen 2" yang hampir universal), representasi dari 0dan -0adalah sama. (Mereka dapat berbeda untuk representasi angka lainnya, misalnya, titik mengambang IEEE 754.)


9
>> Dengan asumsi representasi komplemen 2
Marco A.

12

Mari kita mulai dengan merepresentasikan 0 dalam komplemen 2 (tentu saja ada banyak sistem dan representasi lain, di sini saya merujuk yang spesifik ini), dengan asumsi 8-bit, nol adalah:

0000 0000

Sekarang mari balik semua bit dan tambahkan 1 untuk mendapatkan komplemen 2:

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

kami dapatkan 0000 0000, dan itu juga representasi dari -0.

Tetapi perhatikan bahwa dalam pelengkap 1, tanda 0 adalah 0000 0000, tetapi -0 adalah 1111 1111.


1
Bisakah saya tahu mengapa suara negatif untuk meningkatkan jawaban saya?
Maroun

1
Meskipun sebagian besar jawaban lain secara teknis benar, jawaban Anda praktis, dan menyediakan implementasi. Baik.
umlcat

9

Saya telah memutuskan untuk membiarkan jawaban ini karena implementasi C dan C ++ biasanya terkait erat, tetapi pada kenyataannya tidak tunduk pada standar C seperti yang saya kira. Intinya tetap bahwa standar C ++ tidak menentukan apa yang terjadi untuk kasus seperti ini. Juga relevan bahwa representasi non-dua-komplemen sangat langka di dunia nyata, dan bahkan jika memang ada, mereka sering menyembunyikan perbedaan dalam banyak kasus daripada memaparkannya sebagai sesuatu yang dapat diharapkan dengan mudah ditemukan seseorang.


Perilaku nol negatif dalam representasi integer di mana mereka ada tidak didefinisikan secara ketat dalam standar C ++ seperti dalam standar C. Namun, ia mengutip standar C (ISO / IEC 9899: 1999) sebagai referensi normatif di tingkat atas [1.2].

Dalam standar C [6.2.6.2], nol negatif hanya dapat menjadi hasil dari operasi bitwise, atau operasi di mana sudah ada nol negatif (misalnya, mengalikan atau membagi nol negatif dengan nilai, atau menambahkan nol negatif ke nol) - menerapkan operator minus unary ke nilai nol normal, seperti dalam contoh Anda, oleh karena itu dijamin menghasilkan nol normal.

Bahkan dalam kasus yang dapat menghasilkan nol negatif, tidak ada jaminan bahwa mereka akan melakukannya, bahkan pada sistem yang mendukung nol negatif:

Tidak ditentukan apakah kasus ini benar-benar menghasilkan nol negatif atau nol normal, dan apakah nol negatif menjadi nol normal saat disimpan dalam suatu objek.

Oleh karena itu, kami dapat menyimpulkan: tidak, tidak ada cara yang dapat diandalkan untuk mendeteksi kasus ini. Bahkan jika bukan karena fakta bahwa representasi non-dua-komplemen sangat tidak umum dalam sistem komputer modern.

Standar C ++, pada bagiannya, tidak menyebutkan istilah "nol negatif", dan hanya memiliki sedikit diskusi tentang rincian besaran yang ditandatangani dan representasi pelengkap seseorang, kecuali untuk dicatat [3.9.1 para 7] bahwa mereka diperbolehkan.


Secara umum tidak, fakta bahwa sesuatu itu benar / diperlukan dalam C tidak berarti itu benar / diperlukan dalam C ++. Fakta bahwa C adalah referensi normatif berarti C ++ mengacu pada standar C untuk berbagai hal (terutama isi header standar), tetapi definisi tipe integer bukanlah salah satu dari hal-hal itu. Namun, tidak adanya cara yang dijamin untuk menghasilkan nol negatif berarti apa yang Anda simpulkan masih benar, tidak ada cara pasti untuk membuatnya menggunakan aritmatika meskipun representasi tersebut ada.
Steve Jessop

Lalu mengapa standar C ++ kurang mendetail tentang hal-hal seperti ini?
Acak832

1
Selera pribadi, menurut saya, jika jumlah orang yang memberikan suara pada standar C ++ dapat dianggap "pribadi" :-) Jika akan tunduk pada standar C untuk definisi, maka itu bisa berfungsi dengan baik dan tidak berisi detail, seperti di beberapa kasus lain.
Steve Jessop

Apakah "C ++ adalah bahasa pemrograman bertujuan umum berdasarkan bahasa pemrograman C seperti yang dijelaskan dalam ISO / IEC 9899: 1999 Bahasa pemrograman - C (selanjutnya disebut sebagai standar C)." [1.1 para 2] memiliki arti normatif? Saya pikir itu dimaksudkan untuk secara umum menggabungkan standar C untuk apa pun yang tidak secara khusus diganti oleh standar C ++.
Acak832

@ Random832 Tidak. Ini hanya catatan sejarah (ada, misalnya, tidak ada _Boolatau _Complexatau penginisialisasi yang ditunjuk atau literal gabungan dalam C ++). Standar C ++ tahu bagaimana menggabungkan standar C ketika ia ingin - misalnya, [basic.fundamental] / p3: "Tipe bilangan bulat bertanda dan tak bertanda harus memenuhi batasan yang diberikan dalam standar C, bagian 5.2.4.2.1."
TC

8

Jika mesin Anda memiliki representasi berbeda untuk -0dan +0, maka memcmpakan dapat membedakannya.

Jika bit padding ada, sebenarnya mungkin ada beberapa representasi untuk nilai selain nol juga.


5

Dalam spesifikasi bahasa C ++, tidak ada int seperti nol negatif .

Satu-satunya arti yang dimiliki kedua kata tersebut adalah operator unary yang -diterapkan 0, seperti tiga ditambah lima hanyalah operator biner yang +diterapkan ke 3dan 5.

Jika terdapat nol negatif yang berbeda , komplemen dua (representasi paling umum dari jenis bilangan bulat) akan menjadi representasi yang tidak memadai untuk implementasi C ++, karena tidak ada cara untuk merepresentasikan dua bentuk nol.


Sebaliknya, floating point (mengikuti IEEE) memiliki nol positif dan negatif yang terpisah. Mereka dapat dibedakan, misalnya, saat membagi 1 dengan mereka. Nol positif menghasilkan tak terhingga positif; nol negatif menghasilkan tak terhingga negatif.


Namun, jika kebetulan ada representasi memori yang berbeda dari int 0 (atau int apa pun, atau nilai lain apa pun dari jenis lainnya), Anda dapat menggunakan memcmpuntuk menemukan bahwa:

#include <string>

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

Tentu saja, jika ini benar-benar terjadi, di luar operasi memori langsung, kedua nilai tersebut akan tetap bekerja dengan cara yang persis sama.


3
Sebenarnya, bahasa tidak mengamanatkan keberadaannya tidak berarti bahasa itu mengamanatkan ketidakhadirannya. Petunjuk: Ini tidak mengamanatkan.
Deduplicator

2
@Deduplicator, semacam. Dengan "dalam bahasa C ++", maksud saya, "dalam spesifikasi bahasa C ++ ". Karena tidak ada penyebutan froobinator dalam spesifikasi, saya dapat mengatakan "C ++ tidak memiliki froobinator" tanpa terlalu banyak ambiguitas. Saya pikir itu jelas, tetapi saya akan memperbaikinya.
Paul Draper

1
Spesifikasi bahasa juga tidak menyebutkan unicorn.
ypercubeᵀᴹ

2

Untuk menyederhanakan saya merasa lebih mudah untuk memvisualisasikan.

Jenis int (_32) disimpan dengan 32 bit . 32 bit berarti 2 ^ 32 = 4294967296 nilai unik . Jadi :

Rentang data int unsigned adalah 0 hingga 4,294,967,295

Dalam kasus nilai negatif itu tergantung pada bagaimana mereka disimpan. Dalam hal

Dalam kasus nilai komplemen One -0 ada.


2
Saya belum menurunkan suara tetapi platform yang inttidak disimpan dalam 32 bit lebih populer daripada platform dengan pelengkap saat ini.
Maciej Piechotka
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.