Почему у C нет беззнаковых поплавков? - PullRequest
113 голосов
/ 04 февраля 2009

Я знаю, вопрос кажется странным. Программисты иногда слишком много думают. Пожалуйста, читайте дальше ...

В C я часто использую signed и unsigned целые числа. Мне нравится тот факт, что компилятор предупреждает меня, если я делаю такие вещи, как присвоение целого числа со знаком переменной без знака. Я получаю предупреждения, если сравниваю подписанные целые числа без знака и многое другое.

Мне нравятся эти предупреждения. Они помогают мне сохранить правильный код.

Почему у нас нет такой же роскоши для поплавков? Квадратный корень определенно никогда не вернет отрицательное число. Есть и другие места, где отрицательное значение с плавающей запятой не имеет значения. Идеальный кандидат для неподписанного поплавка.

Кстати, я не особо заинтересован в том, чтобы получить дополнительный бит точности, который я мог бы получить, удалив знаковый бит из поплавков. Я очень доволен float с, как они сейчас. Я просто хотел бы помечать число с плавающей точкой как беззнаковое иногда и получать те же предупреждения, что и с целыми числами.

Мне неизвестен какой-либо язык программирования, который поддерживает беззнаковые числа с плавающей запятой.

Есть идеи, почему они не существуют?


EDIT:

Я знаю, что у x87 FPU нет инструкций по работе с неподписанными числами. Давайте просто использовать подписанные инструкции с плавающей точкой. Неправильное использование (например, падение ниже нуля) может рассматриваться как неопределенное поведение так же, как переполнение целых чисел со знаком не определено.

Ответы [ 11 ]

0 голосов
/ 27 февраля 2019

IHMO, потому что поддержка типов с плавающей запятой как со знаком, так и без знака в аппаратном или программном обеспечении была бы слишком хлопотной

Для целочисленных типов мы можем использовать одинаковые логические единицы для целочисленных операций как со знаком, так и без знака в большинстве ситуаций, используя свойство nice дополнения 2, потому что результат идентичен в тех случаях для операций сложения, подстановки, расширения без расширения и большинства побитовых операций. Для операций, которые различают подписанную и неподписанную версии, мы все равно можем использовать большую часть логики . Например

  • Арифметический и логический сдвиг требует лишь небольшого изменения в наполнителе для старших бит
  • Расширяющее умножение может использовать то же аппаратное обеспечение для основной части, а затем некоторую отдельную логику для корректировки результата для изменения сигнатуры . Не то чтобы он использовался в реальных множителях, но возможно сделать
  • Сравнение со знаком можно преобразовать в сравнение без знака и наоборот, просто переключив верхний бит или , добавив INT_MIN. Также теоретически возможно, это, вероятно, не используется на оборудовании, но это полезно на системах, которые поддерживают только один тип сравнения (например, 8080 или 8051)

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

К сожалению мы не можем позволить себе такую ​​роскошь для типов с плавающей точкой. Просто освободив знаковый бит, мы получим версию без знака. Но тогда для чего нам этот бит?

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

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

В системах, которые используют программную точку с плавающей точкой, вам нужно 2 версии для каждой функции, которая не ожидалась в то время, когда память была слишком дорогой, или вам нужно было бы найти какой-нибудь «хитрый» способ поделиться частями подписанного и беззнаковые функции

Однако аппаратное обеспечение с плавающей запятой существовало задолго до того, как был изобретен C , поэтому я считаю, что выбор в C был обусловлен отсутствием аппаратной поддержки из-за причины, о которой я упоминал выше

Тем не менее, существует несколько специализированных беззнаковых форматов с плавающей запятой, в основном для обработки изображений, таких как 10- и 11-битный тип с плавающей запятой группы Khronos

...