2016-01-25 2 views
-3

Есть ли способ в C++ к типажу в двойной в поплавке, int32, Uint8 или Егобез потери информации? И если невозможно вернуть ошибку?C++ напечатанного двойного

Edit: На самом деле я не был достаточно ясен ...

У меня есть функция, которая получает в качестве параметров двойной и типа. Эта функция должна проверить, могу ли я придать двойной в тип без потери информации.

bool check_type(double value, enumType type) 
{ 
    switch(type) { 
     case enum_uint8: 
      return "check wheter value can be typecasted to type" 
      break; 
     case enum_float: 
      . 
      . 
      . 
    } 
    return false; 
} 
+6

Аналогичный вопрос: Можете ли вы представить состояние двух бит только с одним битом без потери информации? –

+1

Вы всегда можете отливать, отбрасывать и сравнивать. –

+0

@DavidSchwartz Но это просто переинтерпрет/тип каламбура. Значение как 'float' /' int32' и т. Д. Тогда должно считаться бессмысленным или зависимым от реализации. – sehe

ответ

1

Может быть, попробовать что-то вроде этого:

#include <limits> 

template<typename T> 
inline bool is_in_allowed_range(double value) 
{ 
    return (
     (value >= static_cast<double>(std::numeric_limits<T>::min())) && 
     (value <= static_cast<double>(std::numeric_limits<T>::max())) 
    ); 
} 

bool check_type(double value, enumType type) 
{ 
    switch(type) { 
     case enum_uint8: 
      return is_in_allowed_range<uint8>(value); 
     case enum_float: 
      return is_in_allowed_range<float>(value); 
     ... 
    } 
    return false; 
} 

... 

double value = ...; 
if (check_type(value, enum_uint8)) 
{ 
    uint u = static_cast<uint8>(value); 
    // use u as needed ... 
} 

Или проще:

#include <limits> 

template<typename T> 
bool convert_to_type(double value, T *arg) 
{ 
    if ((value >= static_cast<double>(std::numeric_limits<T>::min())) && 
     (value <= static_cast<double>(std::numeric_limits<T>::max()))) 
    { 
     *arg = static_cast<T>(value); 
     return true; 
    } 
    return false; 
} 

... 

double value = ...; 
uint8 u; 
if (convert_to_type(value, &u)) 
{ 
    // use u as needed... 
} 
+0

Преобразование double в float будет вообще потерять информацию (точность), даже если значение попадает внутрь диапазона значений float. Проверка диапазона не является достаточной, чтобы гарантировать преобразование без потерь. – IInspectable

+1

@ iinpectable : true, но в целом все, что вы делаете с числами с плавающей запятой, в общем-то, по сути, довольно схож. –

0

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

Если вы выполняете проверки во время выполнения, вы не можете получить типы переменных в базе C++, но если вы делаете их во время компиляции, вы можете использовать переменную :: typeid для проверки. опция проверки на потерю информации заключается в том, чтобы отбросить один путь до нужного типа, вернуть обратно к предыдущему типу, а затем сравнить результаты, чтобы узнать, была ли потеряна информация.

1

Поскольку double использует больше бит для хранения данных, чем float, если вы храните double в float, есть вероятность, что данные не помещаются в размере float. Поэтому вы потеряете некоторые данные.

В int32, uint8 хранит только целое значение, удваивается в C++ хранятся в виде (1-битового знака) + 2^(11-битный) показателя (52 бит), значительным на общую сумму 64 бита. Таким образом, есть вероятность, что вы потеряете данные. [это взято из комментария]

Но возможно литье.

Кстати, вы можете сгенерировать ошибку, проверив значение в двойном ли оно больше максимального предела типа данных, который вы собираетесь использовать.

+0

Сохранение двоичного файла в типе int неточно. double в C++ хранятся как (1-битный знак) + 2^(11-разрядный показатель) * 1 * (52 бит), всего 64 бит. это означает, что он небезопасен для приведения, поскольку вы arent сохраняете литеральное число, но вычисленное поле –

+1

@ByrenHiggin: конверсии на C++ не являются бит-мутными операциями копирования/обрезания. Они знают, как конвертировать IEEE с плавающей запятой в дополнение к двум (действительно, это сама цель иметь систему типов в первую очередь). И _literals_ полностью ортогональны этому. –

+0

Да, @ByrenHiggin, вы правы. Я добавил это к моему ответу. – MASh

2

Нет. Это было бы как сжигать вашу собаку, чтобы вы могли поместить ее в урну для более удобного перемещения дома, а затем удивляясь, когда узнаете, что вы не можете снова отменить ее снова.

Вы обычно получаете компилятор предупреждение если преобразование рисков потери данных (это называется «сужение преобразования»), но так как это зависит от начальных значений, которые, как правило, известны только во время выполнения, вы не можете получить компилятор ошибка для этого & hellip; и «легкая» парадигма C++ препятствует разработчикам языка, чтобы ваша программа выдавала исключение или что-то еще во время выполнения.

+0

'Собака && spot = std :: move (пепел); // Ошибка компилятора ??? ' – erip

+0

@erip: Плохое :( –