Из-за соображений безопасности мне нужно выполнить одно и то же вычисление дважды, один раз с переменными integer (int32) и в другое время с только переменными float (float32). В конце вычислений проводится сравнение между двумя результатами.
Я прочитал статью о сравнении чисел с плавающей запятой.
Есть несколько вещей, которые я не понимаю:
У меня нет следующего сжатия для числа с плавающей запятой. Предполагая, что a и b являются поплавками, этот способ сравнения правильный:
if! (a> b) &&! (a <b) истинно, то a и b, вероятно, идентичны в противном случае.
Если я поместил число с плавающей точкой в целое число, я получу целочисленную часть числа, почему, используя объект union и там определяющий ту же память, что и int32 и float32, я получаю другое решение? Не добавляет ли он число float в int32?
почему, используя объект union и определяя ту же память, что и int32, и float32, я получаю другое решение?
Единственная причина, по которой float/int union
даже имеет смысл, заключается в том, что как float
и int
имеют storage size
32-bits
. Что вам не хватает понимание того, что floats
(на самом деле все числа с плавающей точкой) сохраняется в IEEE-754 Floating Point Format
с IEEE-754 Floating Point Format
(поплавки с одинарной точностью, двойниками являются двойной точностью, и т.д..)
Когда вы используете трюк float/int union
, вы видите integer value
которое является integer equivalent
IEEE-754 Single-Precision Floating Point Format
для float
. Эти два значения не имеют ничего общего с представлением одного и того же числового значения. Вы можете просто посмотреть на память, которую они занимают либо как float
либо как integer
, в силу того, что они занимают 32-bits
память. Если вы просмотрите окно с float
, вы увидите, что означают эти 32-bits
как float
. Если, с другой стороны, вы смотрите на те же 32-bits
что и integer
, вы не видите ничего более того, что те же самые 32-bits
будут приняты, если считать integer
. Обычно помогает пример, рассматривающий двоичное представление.
Возьмем, к примеру, значение float
123.456
. Если вы посмотрите на 32-bits
память, вы увидите:
The float value entered : 123.456001
binary value in memory : 01000010-11110110-11101001-01111001
As unsigned integer : 1123477881
Представление одноточечной плавающей точки IEEE-754 представляет собой особый формат с плавающей запятой в памяти, состоящий из следующих трех компонентов:
0 1 0 0 0 0 1 0 1 1 1 1 0 1 1 0 1 1 1 0 1 0 0 1 0 1 1 1 1 0 0 1
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
|s| exp | mantissa |
Где s
- sign-bit
, exp
- это biased exponent
с остальными 23-bits
называемыми mantissa
. Нельзя ожидать, что вы будете использовать float 123.456
и получить что-нибудь близкое к integer 123
, вы отключены примерно на 7 orders of magnitude
Не добавляет ли он число float в int32?
Ответ: Нет
Ложь. Сравнение типов с плавающей точкой совпадает с целыми числами, за исключением специальных чисел, таких как nan и inf. a == b
всегда возвращает true, если значение a точно равно b, то есть 12.345 == 12.345
но 12.345 < 12.346
. Если вам нужно сравнить, что значение достаточно близко друг к другу, используйте epsilon like FatihK
Простое (int)some_double_value
в int like (int)some_double_value
просто вернет значение some_double_value. Однако, если вы храните его в объединении и зачитываете целое число, подобное этому, оно вернет представление в память float
Например (int) 2.5 == 2, но двоичное представление 2.5 в двойной точности IEEE-754 равно 0x4004000000000000
a
и b
оба nan
, и в этом случае a < b
, a > b
, a == b
все ложные.float
в int
(например, от 1.0f
до 1
), их память не является одинаковой.