Я должен умножить целочисленное значение на 2 ^ 31. Я гуглил это, и похоже, что у двойников есть диапазон между 2.23e-308 <= | X | <= 1.79e308 при использовании 64 бит и число с плавающей запятой среди 1.18e-38 <= | X | <= 3.40e38.
Это намного больше, чем мне нужно. Но это не работает.
У меня есть это постоянное значение в моем заголовочном файле:
static const float SCALE_FACTOR = 2^-31;
и если тогда я просто делаю:
float dummy = SCALE_FACTOR;
Тогда значение макета равно 11.
Я не знаю, если проблема заключается в том, чтобы присвоить постоянное значение, как это, но я не знаю, как еще написать это без потери точности.
Любая помощь?
РЕДАКТИРОВАТЬ: Извините, глупый вопрос. Мой опыт в MatLab предал меня и забыл, что ^ не для возведения в степень в C ++. Я проголосовал за закрытие.
^ — побитовый оператор xor в C ++, а не математический оператор возведения в степень. У вас есть несколько альтернатив.
float
Можно просто отработать базу-10 e
Форма буквально и использовать это: возможно, что-то вроде 4.6566128730773926e-010
за 2 ^ -31. Это подвержено ошибкам (например, я их сделал) и не обязательно переносимо между форматами с плавающей запятой.0x80000000
или же 1UL << 31
за 2 ^ 31 или 1.0f / 0x80000000
для 2 ^ -31 например.Вы могли бы использовать pow
Конечно, функция для вычисления значения во время выполнения.
Кстати, если вы используете целые числа, почему бы просто не использовать long long
или другой 64-битный целочисленный тип вместо плавающей запятой, который вполне может представить вам ошибки округления? Из вашего вопроса не совсем понятно, смотрите ли вы на значения с плавающей запятой, потому что вы необходимость диапазоны значений с плавающей запятой или потому, что вы просто беспокоитесь о переполнении 32-битного целочисленного значения.
В вашем коде
static const float SCALE_FACTOR = 2^-31;
static
избыточно (константы имеют внутреннюю связь по умолчанию), ^
обозначает побитовое XOR, -
бессмысленно (по крайней мере, если вы хотите «умножить на 2 ^ 31», как указано), и float
без необходимости особый выбор, в отличие от типа с плавающей точкой по умолчанию double
(например, это тип литерала с плавающей запятой, такой как 3.14
).
Также в C ++ резервный крик ВСЕХ UPPERCASE-идентификаторов для макросов (общее соглашение). Использование их для констант — это Java-изм. По иронии судьбы соглашение Java возникло в C, где в прошлом константы должны были выражаться как макросы.
Вместо этого пишите
double const scale_factor = 1uL << 31;
где
не указывать явно внутреннюю связь (ключевое слово static
),
используя тип с плавающей точкой по умолчанию double
вместо float
,
не использовать ALL UPPERCASE идентификатор (который должен быть зарезервирован для макросов),
используя левое смещение <<
вычислить степень двух вместо неправильных ^
,
не добавляя ни одного бессмысленного знака минус,
используя тип unsigned long
(указано uL
) чтобы быть уверенным, чтобы иметь достаточный диапазон.
^
является оператором для побитового XOR, а не для возведения в степень. Тебе нужно std::pow()
,
Умножение на степень 2 эквивалентно сдвигу влево на эту степень. Чтобы умножить целое число на два до 31, просто сдвиньте его:
unsigned long value = whatever;
unsigned long value_times_2_to_the_31 = value << 31;
Там нет необходимости для математики с плавающей точкой здесь. Но для полноты, чтобы получить двойное значение от 2 до 31:
double two_to_the_31 = std::ldexp(1.0, 31);
Обратите внимание, что хотя результат выражения shift со типом со знаком будет формально неопределенным в некоторых ситуациях, это является результатом переполнения целочисленного типа; использование математики с плавающей точкой вместо этого не устраняет переполнение, оно просто помещает его в другую часть кода.