Какая разница между типом данных float и integer при том же размере?
- float хранит значения с плавающей запятой, то есть значения, имеющие потенциальные десятичные знаки
- int хранит только целые значения, т.е. целые числа
Таким образом, хотя оба имеют ширину в 32 бита, их использование (и представление) совершенно иное. Вы не можете хранить 3.141 в целочисленном размере, но можете в float .
Рассеивание их еще немного:
В целых числах все биты используются для хранения значения числа. Это (на Java и многие компьютеры тоже) сделано в так называемом двух дополнит. Это в основном означает, что вы можете представить значения & minus; 2 31 до 2 31 1.
В поплавке эти 32 бита разделяются между тремя отдельными частями: знаковым битом, показателем и мантиссой. Они выложены следующим образом:
Существует один бит, который определяет, является ли число отрицательным или неотрицательным (ноль не является ни положительным, ни отрицательным, но имеет битовый знак, равный нулю). Тогда есть восемь бит экспонента и 23 бит мантиссы. Чтобы получить полезный номер из этого, (примерно) выполняется следующий расчет:
(Для этого есть больше, но этого должно хватить для целей этого обсуждения)
Мантисса по существу не намного больше, чем 24-разрядное целое число. Это умножается на 2 на степень экспоненциальной части, которая, грубо говоря, представляет собой число между & минус 128 и 127.
Поэтому вы можете точно представлять все числа, которые бы вписывались в 24-битное целое число, но числовой диапазон также намного больше, поскольку более крупные экспоненты допускают большие значения. Например, максимальное значение для float составляет около 3,4 × 10 38 тогда как int допускает значения до 2,1 × 10 9 .
Но это также означает, что, поскольку 32 бита имеют только 4,2 × 10 9 различные состояния (которые все используются для представления значений int могут хранить), что на большем конце float числовые номера отличаются друг от друга разнесенными друг от друга (поскольку число уникальных float не может быть больше, чем уникальные числа int ). Вы не можете точно представлять некоторые цифры. Например, число 2 × 10 12 имеет представление в float от 1 999 999 991 808. Это может быть близко к 2 000 000 000 000, но это не точно. Аналогично, добавление 1 к этому номеру не изменяет его, потому что 1 слишком мал, чтобы сделать разницу в больших масштабах float используется там.
Аналогично, вы можете также представлять очень маленькие числа (от 0 до 1) в float , но независимо от того, являются ли эти цифры очень большими или очень маленькими, float имеет точность около 6 или 7 десятичных цифр, Если у вас есть большие числа, эти цифры находятся в начале номера (например, 4.51534 × 10 35 то есть не более 451534 следует 30 нулями — и float не может сказать ничего полезного о том, 30 цифр — это нули или что-то еще), для очень маленьких чисел (например, 3.14159 × 10 & minus; 27 ) они находятся в дальнем конце номера, за пределами стартовых цифр 0,0000.
Скомпилировать и запустить мой код; сравните результат, если вы используете целые числа или числа с дробными значениями. Почему есть разница?
Я не смог найти разницу между двумя результатами при использовании целочисленных значений и при использовании чисел с плавающей запятой.
Решение
Проблема в том, что нельзя сравнивать поплавки с == из-за внутреннего представления чисел с плавающей запятой. Если вы используете результат из выражения, математически может быть правильно найти число в массиве, но из-за ограничений в представлении с плавающей точкой == не нашел бы это.
Рассмотрим следующий код:
Итак, хотя 1.0 / 0.3333 * 0.3333 является 1.0 математически, это не при использовании арифметики с плавающей запятой — это 0.99999 вместо. Следовательно == не считает числа равными в последнем сравнении.
Чтобы решить эту проблему, сравните разницу двух чисел с небольшим epsilon значение. float.h явно определяет константу FLT_EPSILON за это:
Размер указателя один и тот же, если вы это имеете ввиду.
char* отличается от int* тем, что первый указывает на область памяти в sizeof(char) байт, а второй в sizeof(int) байт. Это важно, например для адресной арифметики.
Например имеем:
Если мы делаем pc++, то к pc прибавляется sizeof(char), а в случае pi++ к pi прибавляется sizeof(int).
А так же, когда мы делаем разъименование, то получаем в результате соответствующий тип:
*pc — дает char
*pi — дает int
Если бы не было типизации указателей, то не было бы и адресной арифметики и разъименования. Посмотрите, например, что можно сделать с указателем на void.