Wiem, że wartości całkowite 0
i -0
są zasadniczo takie same. Zastanawiam się jednak, czy można je rozróżnić.
Na przykład, skąd mam wiedzieć, czy zmienna została przypisana -0
?
bool IsNegative(int num)
{
// How ?
}
int num = -0;
int additinon = 5;
num += (IsNegative(num)) ? -addition : addition;
Czy wartość -0
zapisana w pamięci jest dokładnie taka sama jak 0
?
c++
int
zero
negative-number
Filip Minx
źródło
źródło
int
jest reprezentowany w uzupełnieniu 2 (zdecydowanie najczęściej spotykanym)0
i-0
ma identyczne reprezentacje bitowe.int
. Zobacz kodowanie dopełniające Ones .Odpowiedzi:
To zależy od maszyny, na którą celujesz.
Na komputerze używającym reprezentacji dopełnienia do 2 dla liczb całkowitych nie ma różnicy na poziomie bitów między
0
a-0
(mają tę samą reprezentację)Gdyby twoja maszyna korzystała z dopełniacza , zdecydowanie możesz
0000 0000 -> signed 0 1111 1111 -> signed −0
Oczywiście mówimy o używaniu natywnej obsługi , procesory z serii x86 mają natywną obsługę uzupełniającej reprezentacji podpisanych liczb. Korzystanie z innych reprezentacji jest zdecydowanie możliwe, ale prawdopodobnie byłoby mniej wydajne i wymagałoby więcej instrukcji.
(Jak zauważył również JerryCoffin: nawet jeśli czyjeś uzupełnienie było rozważane głównie z powodów historycznych, reprezentacje wielkości ze znakiem są nadal dość powszechne i mają oddzielną reprezentację dla zera ujemnego i dodatniego)
źródło
0
i czy-0
są inne ? Szczerze mówiąc, spodziewałbym się, że będzie zachowywał się bardziej jak zezwalanie na dwie bitowe reprezentacje tej samej wartości, a twój program może używać tego, na co się wydaje.-0
, to znaczy wynik zastosowania-
operatora jednoargumentowego do stałej liczby całkowitej0
, jest reprezentacją ujemnego zera. Niezależnie od reprezentacji, standard nigdy nie mówi0
i-0
są matematycznie różnymi wartościami, tylko że może istnieć wzór bitowy ujemny-zero. Jeśli tak, nadal reprezentuje tę samą wartość liczbową, 0.Dla
int
(w prawie uniwersalnej reprezentacji „dopełnienia do 2”) reprezentacje0
i-0
są takie same. (Mogą być różne dla innych reprezentacji liczb, np. Zmiennoprzecinkowe IEEE 754).źródło
Zacznijmy od przedstawienia 0 w uzupełnieniu do 2 (oczywiście istnieje wiele innych systemów i reprezentacji, tutaj odnoszę się do tego konkretnego), przy założeniu, że 8-bitowe zero to:
0000 0000
Teraz odwróćmy wszystkie bity i dodajmy 1, aby uzyskać dopełnienie do 2:
1111 1111 (flip) 0000 0001 (add one) --------- 0000 0000
mamy
0000 0000
, i to jest również reprezentacja -0.Ale pamiętaj, że w uzupełnieniu 1 ze znakiem 0 to 0000 0000, ale -0 to 1111 1111.
źródło
Postanowiłem pozostawić tę odpowiedź, ponieważ implementacje C i C ++ są zwykle ściśle powiązane, ale w rzeczywistości nie odstają od standardu C, jak myślałem. Chodzi o to, że standard C ++ nie określa, co się dzieje w takich przypadkach. Istotne jest również to, że reprezentacje dopełniające inne niż dwójki są niezwykle rzadkie w prawdziwym świecie, a nawet tam, gdzie istnieją, często ukrywają różnicę w wielu przypadkach, zamiast ujawniać ją jako coś, czego ktoś mógłby z łatwością oczekiwać.
Zachowanie zer ujemnych w reprezentacjach liczb całkowitych, w których istnieją, nie jest tak rygorystycznie zdefiniowane w standardzie C ++, jak w standardzie C. Cytuje jednak normę C (ISO / IEC 9899: 1999) jako odniesienie normatywne na najwyższym poziomie [1.2].
W standardzie C [6.2.6.2] ujemne zero może być wynikiem tylko operacji bitowych lub operacji, w których ujemne zero jest już obecne (na przykład mnożenie lub dzielenie ujemnego zera przez wartość lub dodanie ujemnego zera do zero) - zastosowanie jednoargumentowego operatora minus do wartości normalnego zera, tak jak w twoim przykładzie, gwarantuje zatem normalne zero.
Nawet w przypadkach, które mogą wygenerować ujemne zero, nie ma gwarancji, że tak się stanie, nawet w systemie, który obsługuje ujemne zero:
Dlatego możemy stwierdzić: nie, nie ma niezawodnego sposobu na wykrycie tego przypadku.Nawet gdyby nie fakt, że reprezentacje z dopełnieniem innym niż dwójki są bardzo rzadkie w nowoczesnych systemach komputerowych.
Standard C ++ ze swojej strony nie wspomina o terminie „ujemne zero” i zawiera bardzo mało dyskusji na temat szczegółów wielkości ze znakiem i reprezentacji dopełnień, z wyjątkiem uwagi [3.9.1 akapit 7], że są one dozwolone.
źródło
_Bool
lub_Complex
czy wyznaczone inicjalizatory lub związek literały w C ++). Standard C ++ wie, jak włączyć standard C, kiedy chce - np. [Basic.fundamental] / p3: "Typy liczb całkowitych ze znakiem i bez znaku powinny spełniać ograniczenia podane w standardzie C, sekcja 5.2.4.2.1."Jeśli twoja maszyna ma różne reprezentacje dla
-0
i+0
, wtedymemcmp
będzie w stanie je rozróżnić.Jeśli obecne są bity wypełniające, w rzeczywistości może istnieć wiele reprezentacji wartości innych niż zero.
źródło
W specyfikacji języka C ++ nie ma takiej liczby int, jak ujemne zero .
Jedyne znaczenie, jakie mają te dwa słowa, to operator jednoargumentowy
-
zastosowany do0
, tak jak trzy plus pięć to po prostu operator binarny+
zastosowany do3
i5
.Gdyby istniało wyraźne ujemne zero , uzupełnienie do dwóch (najczęstsza reprezentacja typów całkowitych) byłoby niewystarczającą reprezentacją dla implementacji C ++, ponieważ nie ma sposobu, aby przedstawić dwie formy zera.
W przeciwieństwie do tego zmiennoprzecinkowe (po IEEE) mają oddzielne zera dodatnie i ujemne. Można je rozróżnić np. Dzieląc przez siebie 1. Dodatnie zero daje dodatnią nieskończoność; ujemne zero daje ujemną nieskończoność.
Jeśli jednak zdarzy się, że istnieją różne reprezentacje pamięci int 0 (lub dowolnej wartości int lub dowolnej innej wartości dowolnego innego typu), możesz użyć,
memcmp
aby odkryć, że:#include <string> int main() { int a = ... int b = ... if (memcmp(&a, &b, sizeof(int))) { // a and b have different representations in memory } }
Oczywiście, gdyby tak się stało, poza bezpośrednimi operacjami pamięciowymi te dwie wartości nadal działałyby dokładnie w ten sam sposób.
źródło
Aby uprościć, łatwiej było mi wizualizować.
Typ int (_32) jest przechowywany z 32 bitami . 32 bity oznaczają 2 ^ 32 = 4294967296 unikalnych wartości . Zatem:
Zakres danych bez znaku int wynosi od 0 do 4 294 967 295
W przypadku wartości ujemnych zależy to od sposobu ich przechowywania. W razie
W przypadku dopełnienia do jedynki istnieje wartość -0.
źródło
int
nie są przechowywane w 32 bitach, są obecnie bardziej popularne niż platformy z własnym uzupełnieniem.