Я смотрел http://www.joelonsoftware.com/items/2011/06/27.html и смеялся над шуткой Джона Скита о 0,3, а не 0,3. Лично у меня никогда не было проблем с плавающими / десятичными / двойными числами, но потом я помню, что я выучил 6502 очень рано и никогда не нуждался в плаваниях в большинстве моих программ. Единственный раз, когда я использовал это, было для графики и математики, где неточные числа были в порядке, и вывод был для экрана и не должен быть сохранен (в БД, файле) или зависеть от.
У меня вопрос, где вы обычно использовали числа с плавающей запятой / десятичные числа / двойные? Так что я знаю, чтобы не упустить эти ошибки. С деньгами я использую long и сохраняю значения с центом, для скорости объекта в игре я добавляю int и делю (или bithift) значение, чтобы узнать, нужно ли мне перемещать пиксель или нет. (Я сделал перемещение объекта за 6502 дня, у нас не было ни деления, ни плавания, но были смены).
Так что мне было в основном любопытно.
источник
Ответы:
Потому что они для большинства целей более точны, чем целые числа.
Теперь как это? «для скорости объекта в игре ...» это хороший пример для такого случая. Скажем, вам нужны очень быстрые объекты, например, пули. Чтобы иметь возможность описывать их движение с помощью целочисленных переменных скорости, вам необходимо убедиться, что скорости находятся в диапазоне целочисленных переменных, то есть вы не можете иметь произвольно точный растр.
Но тогда вы также можете описать некоторые очень медленные объекты, такие как часовая стрелка часов. Так как это примерно на 6 порядков медленнее, чем у объектов маркера, первые ld (10⁶) ≈ 20 бит равны нулю, что исключает
short int
типы с самого начала. Хорошо, сегодня у нас естьlong
s везде, что оставляет нам все еще комфортные 12 бит. Но даже в этом случае тактовая частота будет с точностью до четырех знаков после запятой. Это не очень хорошие часы ... но это, конечно, хорошо для игры. Просто вы бы не хотели делать растр намного грубее, чем он есть.... что приводит к проблемам, если однажды вы захотите представить новый, еще более быстрый тип объекта. Не осталось "запаса".
Что произойдет, если мы выберем тип float? Тот же самый размер 32 бита, но теперь у вас есть полные 24 бита точности для всех объектов. Это означает, что часы имеют достаточную точность, чтобы оставаться синхронизированными с точностью до секунды в течение многих лет. Пули не имеют более высокой точности, но в любом случае они «живут» лишь доли секунды, поэтому было бы совершенно бесполезно, если бы они имели. И у вас не будет никаких неприятностей, если вы хотите описать даже гораздо более быстрые объекты (почему бы не скорость света? Нет проблем) или гораздо более медленные. Вам, конечно, не понадобятся такие вещи в игре, но вы иногда делаете это в симуляторах физики.
А с числами с плавающей запятой вы получаете ту же самую точность всегда и без необходимости предварительно выбирать неочевидный растр. Это, пожалуй, самый важный момент, поскольку такие потребности выбора очень подвержены ошибкам.
источник
Вы используете их, когда описываете непрерывное значение, а не дискретное . Это не сложнее описать, чем это. Только не делайте ошибку, предполагая, что любое значение с десятичной точкой является непрерывным. Если все меняется сразу, например, добавляя копейки, это дискретно.
источник
У вас действительно есть два вопроса здесь.
В любом случае, зачем кому-то нужна математика с плавающей точкой?
Как указывает Карл Билефельдт, числа с плавающей точкой позволяют моделировать непрерывные величины - и вы найдете их повсюду - не только в физическом мире, но даже в таких местах, как бизнес и финансы.
Я использовал математику с плавающей точкой во многих, многих областях моей карьеры программиста: химию, работу над AutoCAD и даже написание симулятора Монте-Карло для финансовых прогнозов. Фактически, есть парень по имени Дэвид Э. Шоу, который использовал прикладные методы научного моделирования с плавающей точкой на Уолл-стрит, чтобы заработать миллиарды.
И, конечно же, есть компьютерная графика. Я консультируюсь по разработке приятных глаз для пользовательских интерфейсов, и попытка сделать это в наше время без четкого понимания с плавающей запятой, тригонометрии, исчисления и линейной алгебры - это все равно что сражаться с оружием с помощью карманного ножа.
Зачем кому-то нужен поплавок против двойника ?
В стандартном представлении IEEE 754 32-разрядное число с плавающей запятой дает вам около 7 десятичных знаков точности и показатели в диапазоне от 10 -38 до 10 38 . 64-битный дубль дает около 15 десятичных знаков точности, а показатели в диапазоне от 10 -307 до 10 307 .
Может показаться, что поплавка будет достаточно для того, что кому-то разумно понадобится, но это не так. Например, многие реальные величины измеряются более чем 7 десятичными цифрами.
Но более тонко, есть проблема, в разговорной речи называемая «ошибка округления». Двоичные представления с плавающей запятой действительны только для значений, дробные части которых имеют знаменатель со степенью 2, например 1/2, 1/4, 3/4 и т. Д. Чтобы представить другие дроби, например 1/10, вы «округлите» значение ближайшей двоичной дроби, но это немного неправильно - это «ошибка округления». Затем, когда вы делаете математику с этими неточными числами, неточности в результатах могут быть намного хуже, чем вы начали - иногда процент ошибок увеличивается или даже накапливается экспоненциально.
В любом случае, чем больше двоичных цифр вам нужно работать, тем ближе будет округленное двоичное представление к числу, которое вы пытаетесь представить, поэтому ошибка округления будет меньше. Затем, когда вы выполняете математические расчеты, если у вас есть много цифр для работы, вы можете сделать гораздо больше операций, прежде чем накопительная ошибка округления возрастет до места, где это является проблемой.
На самом деле, 64-битные двойные числа с их 15 десятичными цифрами не достаточно хороши для многих приложений. В 1985 году я использовал 80-битные числа с плавающей запятой, и теперь IEEE определяет 128-битный (16-байтовый) тип с плавающей запятой, который я могу себе представить.
источник
Это распространенное заблуждение, что везде, где вы имеете дело с деньгами, вы должны хранить их значение в виде целого числа (центов). Хотя в некоторых простых случаях, таких как онлайн-магазин, это правда, если у вас есть что-то более продвинутое, это не очень помогает.
Давайте рассмотрим пример: разработчик зарабатывает 100 000 долларов в год. Какова его точная месячная зарплата? Используя целое число, вы получите результат $ 8333,33 (33 833333), умноженный на 12, - $ 99 999,96. Помогло ли это как целое число? Нет, это не так.
Банки всегда используют десятичные / целочисленные значения? Ну, они делают для транзакционной части. Но, например, как только вы начинаете говорить об инвестиционном банкинге, за исключением отслеживания реальных транзакций, все остальное является плавающим. Поскольку это весь внутренний код, вы его не увидите, но вы можете взять пик на QuantLib , который по сути тот же (за исключением гораздо чище ;-).
Зачем использовать поплавки? Потому что использование десятичной дроби совсем не помогает, когда вы используете такие функции, как квадратный корень, логарифмы, степени с нецелыми показателями и т. Д. И, конечно, числа с плавающей запятой намного быстрее, чем типы десятичных чисел.
источник
$100,000/12
и использовали поплавок. Почему результат будет ровно 100 000 долларов? Почему плавающий (или десятичный) округлять вверх или вниз каждый раз, когда кому-то платят? Я имею в виду, когда пишу чек (вы не можете сделать 1/2 или 1/3 цента) или прямой депозит (я предполагаю, что он имеет те же ограничения)То, что вы описали, является отличным обходным решением для ситуаций, когда вы контролируете все входы и выходы .
На самом деле это не так. Вы должны быть в состоянии справиться с системами, которые предоставляют вам свои данные в качестве некоторого реального значения с некоторой степенью точности и ожидаете, что вы вернете данные в том же формате. В таких случаях вы столкнетесь с этими проблемами.
На самом деле вы столкнетесь с этими проблемами, даже если будете использовать перечисленные трюки. При расчете 17,5% налога с цены вы получите дробные центы, независимо от того, сохраняете ли вы стоимость в долларах или центах. Вы должны сделать правильное округление, так как налоговый работник очень расстроен, если вы не заплатите ему достаточно. Использование правильных
money
типов (какими бы они ни были на языке, который вы используете) избавит вас от боли.источник
«Бог сотворил целые числа, все остальное - дело человека». - Леопольд Кронекер (1886).
По определению вам не нужны никакие другие виды чисел. Полнота Тьюринга для языка программирования основана на простых отношениях между различными типами чисел. Если вы можете работать с целыми числами (a / k / a натуральными числами), вы можете делать что угодно.
Вопрос довольно странный, потому что они вам не нужны . Может быть, вы хотите места, где это удобно или оптимально или дешевле или что-то?
источник
В предложении десятичные типы с плавающей точкой инкапсулируют преобразование в целочисленные значения и из них (что все, что компьютер знает, как обращаться на двоичном уровне; в двоичном формате нет десятичной точки), обеспечивая логическую, как правило, простую для понимания понять интерфейс для расчета десятичных чисел.
Откровенно говоря, говорить, что вам не нужны числа с плавающей точкой, потому что вы знаете, как выполнять десятичную математику с использованием целых чисел, - это все равно, что говорить, что вы знаете, как делать арифметические рукописные записи, так зачем использовать калькулятор? Итак, вы знаете концепцию; Браво. Это не значит, что вы должны постоянно использовать эти знания. Часто для недвоичного бизона быстрее, дешевле и понятнее просто сказать 3,5 + 4,6 = 8,1, чем преобразовывать сиг-фиг в целое число.
источник
Основное преимущество типов с плавающей запятой состоит в том, что с точки зрения времени выполнения, два или три формата (я хотел бы, чтобы больше языков поддерживали 80-битные форматы) были бы достаточны для быстрого большинства вычислительных целей. Если бы языки программирования могли легко поддерживать семейство типов с фиксированной запятой, аппаратная сложность, требуемая для данного уровня производительности, часто была бы ниже с типами с фиксированной запятой, чем с плавающей запятой. К сожалению, предоставление такой поддержки далеко не «просто».
Чтобы язык программирования эффективно удовлетворял 98% числовых потребностей приложений, он должен включать десятки типов и предоставлять операции определения для сотен комбинаций; кроме того, даже если бы язык программирования имел прекрасную поддержку с фиксированной запятой, некоторым приложениям все равно нужно было бы поддерживать примерно постоянную относительную точность в достаточно большом диапазоне, чтобы требовать плавающей запятой. Учитывая, что математика с плавающей точкой в некоторых случаях будет необходима в любом случае, если поставщики оборудования сосредоточатся на математической производительности с двумя или тремя форматами с плавающей точкой, а код, использующий эти форматы всякий раз, когда они работают достаточно хорошо, в целом достигнет лучших результатов. «удар на доллар», чем пытаясь оптимизировать поведение математики с фиксированной запятой.
Кстати, математика с фиксированной запятой была более выгодна с 8-битными и 16-битными процессорами, чем с 32-битными. На 8-битном процессоре в ситуации, когда 32-битного не вполне достаточно, 40-битный тип будет стоить только на 25% больше места и на 25-50% больше времени, чем 32-битный тип, и потребует 37,5% меньше места и на 37,5-60% меньше времени, чем у 64-битного типа. На 32-битной платформе, если 32-битный тип не подходит для чего-либо, часто нет особых причин использовать что-либо меньшее, чем 64-битный. Если 48-битный тип с фиксированной запятой будет адекватным, 64-битный «двойной» будет работать так же хорошо, как и тип с фиксированной запятой.
источник
Как правило, вы должны быть очень осторожны в их использовании. Понимание потери точности, которая может возникнуть даже при простых вычислениях, является сложной задачей. Например, усреднение списка чисел как это очень плохая идея:
Причина в том, что для достаточно больших списков вы в основном теряете все точки данных, когда
ans
становитесь достаточно большими (см., Например, это ). Проблема с этим кодом в том, что для небольших списков он, вероятно, просто будет работать - он ломается только в масштабе.Лично я думаю, что вы должны использовать их только тогда, когда: а) расчет действительно должен быть быстрым; б) вас не волнует, что результат может быть далеко (если вы действительно не знаете, что делаете).
источник
Одна мысль состоит в том, что вы должны использовать плавающие или двойные представления, когда вам нужно иметь дело со значениями вне целочисленного диапазона.
Современные архитектуры (примерно) имеют диапазон целых чисел со знаком +/- 2 147 483 647 (32 бита) или +/- 9 223 372 036 854 775 807 (64 бита). Без знака увеличивает это в 2 раза.
IEEE 754 плавает (примерно) от +/- 1,4 × 10 ^ −45 до 3,4 × 10 ^ 38. Double расширяет этот диапазон до +/- 5 × 10−324 ± 2,225 × 10 ^ −308, при этом множество условий и особенностей здесь опущено.
Конечно, самая потрясающе очевидная причина в том, что вам может понадобиться представить -0 ;-)
источник
Обычная причина в том, что они быстры, так как JVM обычно использует базовую аппаратную поддержку (если вы не используете строгий fp).
См. Https://stackoverflow.com/questions/517915/when-to-use-strictfp-keyword-in-java, что подразумевает строгий fp.
источник
Вот почему нам нужны 256-битные операционные системы.
Длина Планки (наименьшее расстояние, которое вы можете измерить) = 10 ^ -35 м
. Наблюдаемая вселенная имеет длину 14Bn парсек = 10 ^ 25 м.
Таким образом, вы можете измерить все в единицах длины Планки в виде целых чисел, если у вас есть только 200 бит точности.
источник