Преобразование unsigned типа к signed
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 10.05.06 06:37
Оценка:
Привет всем.

Что-то я конкретно затупил в "понедельник"

Есть две переменных
signed __int64    sv; //результат работы
unsigned __int64  usv; //промежуточная переменная

В usv я формирую значение (например, преобразую из текстового представления). Результат возвращается знаковый — в sv.

Когда я обрабатываю положительное число, все ясно — проверяем, что usv <= _I64_MAX. Вот когда отрицательное — затупил. Изначально был такой код:
if(usv>(static_cast<unsigned __int64>(_I64_MAX))+1)
 return DISP_E_OVERFLOW;

sv=-usv;

Все работало замечательно, пока этот код не увидел VC7
warning C4146: unary minus operator applied to unsigned type, result still unsigned

Ну, думаю, это не порядок и нужно переделать. Написал:
sv=-static_cast<__int64>(usv);

Предупреждение пропало, но меня начало колбасить другое — есть гарантии что здесь нет и не будет проблем? Бинарное представление usv и sv я себе представляю, но вот как максимально корректно (с точки зрения плюсов), без нагромождения if-ов, преобразовать их друг в друга — туплю

Есть желание написать
usv=(~usv)+1;

sv=*reinterpret_cast<const __int64*>(&usv);

-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re: Преобразование unsigned типа к signed
От: Bell Россия  
Дата: 10.05.06 07:44
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Когда я обрабатываю положительное число, все ясно — проверяем, что usv <= _I64_MAX. Вот когда отрицательное — затупил. Изначально был такой код:

КД>
КД>if(usv>(static_cast<unsigned __int64>(_I64_MAX))+1)
КД> return DISP_E_OVERFLOW;

static_cast<unsigned __int64>(_I64_MAX))+1 , это "минус ноль"? :) 

КД>sv=-usv;
КД>

КД>Все работало замечательно, пока этот код не увидел VC7
КД>
КД>warning C4146: unary minus operator applied to unsigned type, result still unsigned
КД>

КД>Ну, думаю, это не порядок и нужно переделать. Написал:
КД>
КД>sv=-static_cast<__int64>(usv);
КД>

КД>Предупреждение пропало, но меня начало колбасить другое — есть гарантии что здесь нет и не будет проблем?

За исключением случая "минус ноль" поведение кода со static_cast вполне предсказуемо:
4.7/3
If the destination type is signed, the value is unchanged if it can be represented 
in the destination type (and bit-field width); otherwise, the value is implementation-defined.

ну а этот самый "минус ноль" все-таки придется проверять отдельно...
Любите книгу — источник знаний (с) М.Горький
Re[2]: Преобразование unsigned типа к signed
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 10.05.06 08:13
Оценка:
Здравствуйте, Bell, Вы писали:

КД>>Когда я обрабатываю положительное число, все ясно — проверяем, что usv <= _I64_MAX. Вот когда отрицательное — затупил. Изначально был такой код:


Тут надо было пояснить, что usv хранит модуль (отрицательного) результата...

КД>>if(usv>(static_cast<unsigned __int64>(_I64_MAX))+1)
КД>> return DISP_E_OVERFLOW;

B>static_cast<unsigned __int64>(_I64_MAX))+1 , это "минус ноль"? :) 

КД>>sv=-usv;
КД>>

Как есть "минус ноль"? Здесь, по-моему, все однозначно.

static_cast<unsigned __int64>(_I64_MAX) дает беззнаковое число, равное максимальному значению знакового типа (9223372036854775807i64)

беззнаковое плюс 1 == беззнаковое. Ведь так?

получаем 9223372036854775807ui64+1==9223372036854775808ui64

Если usv больше этого числа, значит у знакового типа в отрицательном представлении пойдет переполнение.

B>За исключением случая "минус ноль" поведение кода со static_cast вполне предсказуемо:

B>
B>4.7/3
B>If the destination type is signed, the value is unchanged if it can be represented 
B>in the destination type (and bit-field width); otherwise, the value is implementation-defined.
B>

B>ну а этот самый "минус ноль" все-таки придется проверять отдельно...

Что-то я не догнал ... то есть:
if(usv>(static_cast<unsigned __int64>(_I64_MAX))+1)
 return DISP_E_OVERFLOW;

if(usv==static_cast<unsigned __int64>(_I64_MAX))+1)
 return _I64_MIN;

return -static_cast<__int64>(sv);

Меня параноиком не будут обзывать?
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[3]: Преобразование unsigned типа к signed
От: Centaur Россия  
Дата: 10.05.06 11:39
Оценка: 9 (1)
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Тут надо было пояснить, что usv хранит модуль (отрицательного) результата...


КД>
КД>if(usv>(static_cast<unsigned __int64>(_I64_MAX))+1)
КД> return DISP_E_OVERFLOW;
Этот код возврата пересекается с ожидаемым результатом при usv == 2147352566 (на two’s complement платформе).

КД>if(usv==static_cast<unsigned __int64>(_I64_MAX))+1)
КД> return _I64_MIN;

КД>return -static_cast<__int64>(sv); // вероятно, имелось в виду (usv)?
КД>

КД> Меня параноиком не будут обзывать?

Это ещё недостаточно параноидально. Код верен только для случая, если отрицательные числа представляются как two’s complement. А стандарт C допускает также модели sign and magnitude и one’s complement, в которых -2^N тоже непредставимо.

Проверять, живём ли мы под two’s complement или под какой-нибудь симметричной моделью, думаю, можно так:

template <typename Signed, typename Unsigned>
Signed negate(Unsigned u)
{
  typedef std::numeric_limits<Signed> Limits;
  const Unsigned max_magnitude = static_cast<Unsigned>((Limits::max)())
    + ((Limits::min)() + (Limits::max)() == 0 ? 0U : 1U);
  // max_magnitude === |Limits::min()| в терминах «настоящей» арифметики
  if (u > max_magnitude) throw std::overflow_error("overflow"); // заменить обработку ошибок по вкусу
  if (u == max_magnitude) return (Limits::min)();
  // если мы дошли сюда, то преобразование корректно, и отрицание тоже
  return -static_cast<Signed>(u);
}
Re[3]: Преобразование unsigned типа к signed
От: Bell Россия  
Дата: 10.05.06 11:45
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

Все, что про "минус ноль" считать бредом

КД>Что-то я не догнал ... то есть:

КД>
КД>if(usv>(static_cast<unsigned __int64>(_I64_MAX))+1)
КД> return DISP_E_OVERFLOW;

КД>if(usv==static_cast<unsigned __int64>(_I64_MAX))+1)
КД> return _I64_MIN;

КД>return -static_cast<__int64>(sv);
КД>

КД> Меня параноиком не будут обзывать?

Зато нет привязки к способу представления отрицательных чисел...
Любите книгу — источник знаний (с) М.Горький
Re[4]: Преобразование unsigned типа к signed
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 10.05.06 12:13
Оценка: 1 (1) +1 :))
Здравствуйте, Bell, Вы писали:

КД>> Меня параноиком не будут обзывать?


B>Зато нет привязки к способу представления отрицательных чисел...


Спасибо за осмысление моих душевных терзаний...
Когда задумываешься над такими проблемами с "очевидными" решениями, то и хочется обратно к маме
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.