2015-07-03 15 views
5

Mam do czynienia z problemem, w którym liczby całkowite ze znakiem należy konwertować na unsigned, zachowując ich zakres i kolejność.Mapowanie zakresu liczb całkowitych ze znakiem na unsigned

Biorąc pod uwagę następującą definicję:

#include <limits> 

#define MIN(X) std::numeric_limits<X>::min(); 
#define MAX(X) std::numeric_limits<X>::max(); 

Jaki jest najszybszy i poprawny sposób odwzorować podpisany szereg [MIN (T), MAX (T)] do unsigned zakresie [0, MAX (U)]?

gdzie:

T podpisaną typ całkowity

u oznacza liczbę całkowitą bez znaku, typ

sizeof (T) == sizeof (U)

I trie d różne sposoby twiddling i numeryczne, aby wymyślić rozwiązanie, bez powodzenia.

+1

_ "Mam do czynienia z problemem, w którym liczby całkowite ze znakiem powinny zostać przekonwertowane na unsigneds, zachowując ich zakres" _ Er, czego się spodziewałeś "-1"? Czy próbujesz zachować zasięg, ale nie rzeczywistą wartość? Albo co? I dlaczego "różne metody" nie działały dla ciebie? W jaki sposób nie działają? (czym jest "bez powodzenia" w tym kontekście?) Zadaj konkretne pytanie dotyczące określonego podejścia. –

+0

Jeśli zachowujesz zakres, zachowujesz wartość, ponieważ wartość jest określona przez jej pozycję wewnątrz zakresu. Jeśli czytasz pytanie, to wyraźnie chodzi o konwersję zakresu, gdzie -MAX (T) staje się 0. Więc -1 staje się MAX (U)/2 - 1. – plasmacel

+0

@plasmacel Sugeruję edytowanie twojego pytania w celu wyjaśnienia intencji w twoim ostatnim komentarzu . Ogólnie, mapowanie ABC na XYZ będzie na przykład spełnione przez A-> X, B-> Z, C-> Y. –

Odpowiedz

6
unsigned int signedToUnsigned(signed int s) { 
    unsigned int u = 1U + std::numeric_limits<int>::max(); 
    u += s; 
    return u; 
} 

Live example here

Spowoduje to dodanie signed_max + 1 do signed int celu zapewnienia [MIN(int), MAX(int)] jest odwzorowywany [0, MAX(unsigned int)]


Dlaczego praca ta odpowiedź i będzie mapa poprawnie:

Po dodaniu podpisana liczba całkowita t o unsigned, podpisany numer jest promowany do typu unsigned. Z sekcji 4.7 [conv.integral]

Jeżeli typ docelowy jest podpisany otrzymaną wartością jest liczba całkowita bez znaku przynajmniej przystający do całkowitej liczby źródeł (modulo 2 n, gdzie n jest liczbą bitów stosowanych do reprezentowania typu bez znaku). [ Uwaga: w reprezentacji uzupełnienia dwójkowego konwersja ta jest konceptualna i nie ma zmiany w wzorze bitowym (jeśli nie ma obcięcia ). -end note]

+2

Doskonałe wyjaśnienie w cytowanym standardzie. – namezero

+1

Rzeczywiście, dokładnie to, co chciałem! – plasmacel

+1

@plasmacel jako twoje określone typy arbitralne, zostawię to jako zwykłe stwierdzenie, że jest to również możliwe jako ogólny szablon z odpowiednim użyciem 'std ::: make_unsigned' i trochę kreatywnego SFINAE. – WhozCraig

Powiązane problemy