В чем выгода принятия неточностей с плавающей запятой в c # - PullRequest
5 голосов
/ 05 января 2011

Я думал об этой проблеме последний несколько дней, и я изо всех сил пытаюсь сформулировать свой вопрос. Тем не менее, я думаю, что прибил то, что хочу знать.

Почему c # принимает неточность, используя плавающие точки для хранения данных? И в чем преимущество его использования по сравнению с другими методами?

Например, Math.Pow(Math.Sqrt(2),2) не является точным в c #. Существуют языки программирования, которые могут его точно вычислить (например, Mathematica).

Один аргумент, который я мог бы придумать, заключается в том, что его точное вычисление намного медленнее, чем простое решение с неточностью, но Mathematica и Matlab используются для вычисления гигантских научных проблем, поэтому мне трудно поверить, что эти языки действительно значительно медленнее чем с #.

Так почему же тогда?

PS: извините за спам с этими вопросами, вы все очень помогли

Ответы [ 8 ]

32 голосов
/ 05 января 2011

Почему c # принимает неточность, используя плавающие точки для хранения данных?

«C #» не допускает компромисса между производительностью и точностью;пользователи принимают или не соглашаются с этим.

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

float и double хороши для «научных» вычислений, где ответ, правильный для трех или четырех десятичных знаков, всегда достаточно близок, потому что это точность, с которой исходное измерение пришло.Предположим, что вы разделите 10,00 на 3 и получите 3.333333333333.Поскольку исходное измерение, вероятно, было точным только до 0,01, тот факт, что вычисленный результат отклоняется менее чем на 0,0000000000004, не имеет значения.В научных расчетах вы не представляете известные точные величины. Неточность в пятнадцатом десятичном знаке не имеет значения, если исходное значение измерения было точным только до второго десятичного знака .

Это, конечно, неверно для финансовых расчетов.Операнды для финансового расчета обычно являются точными с точностью до двух десятичных знаков и представляют точные величины .Десятичная дробь хороша для «финансовых» вычислений, потому что результаты десятичной операции точны при условии, что все входы и выходы могут быть представлены точно как десятичные дроби (и все они находятся в разумном диапазоне).Конечно, десятичные дроби по-прежнему имеют ошибки округления, но точные операции - это именно те операции, которые вы, вероятно, захотите быть точными при выполнении финансовых расчетов.

И в чем преимущество его использования по сравнению с другимиметоды?

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

Например, Math.Pow (Math.Sqrt (2), 2) не является точным в c #.Существуют языки программирования, которые могут его точно вычислить (например, Mathematica).

Давайте проясним этот момент;Mathematica не "точно вычисляет" корень 2;число нерационально, поэтому оно не может быть точно рассчитано при любом конечном объеме памяти.Вместо этого Mathematica представляет числа как объекты, которые описывают, как было создано число.Если вы говорите «дай мне квадратный корень из двух», то Mathematica по существу выделяет объект, который означает «применение оператора квадратного корня к точному числу 2».Если вы затем возводите это в квадрат, у него есть логика специального назначения, которая гласит: «Если вы возводите в квадрат что-то, что было квадратным корнем чего-то другого, верните первоначальное значение».Mathematica имеет объекты, которые также представляют различные специальные числа, такие как pi или e, и огромное количество правил для того, как различные манипуляции с этими числами объединяются.

По сути, это символическая система;он манипулирует числами так же, как люди, когда делают математику с карандашом и бумагой.Большинство компьютерных программ манипулируют числами, как калькулятор: выполняйте вычисления немедленно и округляйте их.Если это неприемлемо, тогда вам следует придерживаться символической системы.

Один из аргументов, который я могу придумать, заключается в том, что его вычисление точно намного медленнее, чем простое преодоление неточностей, но Mathematica и Matlabиспользуется для вычисления гигантских научных задач, поэтому мне трудно поверить, что эти языки действительно значительно медленнее, чем c #.

Дело не в том, что они медленнее, хотя умножение чисел с плавающей запятой действительно невероятно быстросовременное оборудование.Дело в том, что механизм символьных вычислений чрезвычайно сложен .Он кодирует все правила базовой математики , и таких правил много!C # не предназначен для того, чтобы быть средством символьных вычислений профессионального уровня, он предназначен для языка программирования общего назначения.

12 голосов
/ 05 января 2011

Одним словом: производительность.Арифметика с плавающей запятой, как правило, реализуется на аппаратном уровне и на много порядков быстрее, чем другие подходы.

Более того, ваш пример MATLAB - фиктивный.MATLAB использует арифметику с плавающей запятой двойной точности, как C #.

3 голосов
/ 05 января 2011

Почему c # принимает неточность, используя плавающие точки для хранения данных?

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

Для других способов представления значений с плавающей запятой необходимо программное решение, этозначительно медленнее и требует больше места.«Любой» может реализовать это с помощью того, что доступно в c #, включая встроенную поддержку плавающей запятой для доступного оборудования, было бы довольно трудно для «любого», если бы это еще не поддерживалось в языке / CLR.

2 голосов
/ 05 января 2011

Для большинства проблем программирования неточность не является проблемой, и float (или double) типы данных достаточно хороши. Много лет назад не существовало понятия «значения с плавающей запятой», и программное обеспечение должно было хранить такие значения как два целых числа. А производительность была проблемой (не говоря уже об ошибках программирования - и сценариях wtf - из пользовательских функций вычисления с плавающей запятой). Таким образом, было разработано соглашение, и вскоре после того, как компьютеры были оснащены FPU s.

Теперь, когда использовать FPU для расчетов или использовать другие математические библиотеки / программы (такие как Mathematica), зависит от проблемы. Например, при вычислении вершин в трехмерной среде производительность выше точности. Но бухгалтерское программное обеспечение отличается. В этом аспекте обе проблемы различаются; бухгалтерскому программному обеспечению не нужно будет вычислять комплексные числа миллионы раз в секунду :) ( edit : или, если это произойдет, какое-то очень дорогое оборудование, вероятно, тоже будет частью уравнения!)

Если вы знаете , что вы будете выполнять Math.pow (Math.sqrt (2), 2), вам следует переосмыслить способ хранения обоих значений (например, каждый раз пересчитывать их). Это не проблема с языком программирования, а скорее концептуальная проблема.

0 голосов
/ 05 января 2011

Здесь есть немного объяснений здесь для mathematica

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

Если вам нужна точность, то программист должен написать алгоритм с требуемой степенью точности. Который будет медленнее.

0 голосов
/ 05 января 2011

Одна из причин в том, что числа и числовые форматы однозначны и универсальны. Да, есть ошибки округления, но они постоянны и предсказуемы. Попытка установить общий формат для любой алгоритмической задачи не тривиальна.

0 голосов
/ 05 января 2011

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

Более того, C # не тот, кто принимает неточность. Программист делает. Для большого набора проблем неточность допустима. Float не должен использоваться, когда ожидается точный результат, но это решение для программиста, а не для языкового дизайнера.

0 голосов
/ 05 января 2011

C # и большинство других языков (кроме определенных, таких как Matlab) хранят числа с плавающей запятой в виде полей фиксированного размера (6 или 8 байт), что приводит к неточности.

...