2012-09-29 5 views
-4

Я изучаю TDD и решил создать класс калькулятора для запуска. Сначала я сделал основной, и теперь я нахожусь на функции Square Root.C# Вычитание неточно даже с десятичными знаками?

Я использую этот метод для получения корня http://www.math.com/school/subject1/lessons/S1U1L9DP.html Я проверил его с несколькими номерами, и я всегда получаю точные ответы. довольно легко понять.

Теперь у меня странная проблема, потому что с некоторыми номерами я получаю правильный ответ, а с некоторыми - нет.

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

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

, когда я делаю:

18/4.25 

В настоящее время я получаю: 4.2352941176470588235294117647

, когда оно должно быть: 4.2352941176470588235294117647059 (с помощью окна калькулятор)

в конце пути, это ближайший я добираюсь до корня 18:

4.2426406871192851464050688705^2 = 18.000000000000000000000022892 

мой вопрос:

Могу ли я уточнить это?

+0

Как работает арифметика с плавающей запятой: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html – duffymo

+0

Когда вы говорите «десятичный», вы имеете в виду «десятичный» тип ? Или вы используете 'double' или' float'? –

+0

@ThomasLevesque i означает десятичный тип – samy

ответ

6

4.2352941176470588235294117647 содержит 29 цифр.

decimal определяет, имеет ли 28-29 значащих цифр. Вы не можете сохранить более точный номер в decimal.

В какой области техники или науки вы работаете, где 30-я и болеезначные цифры являются значимыми для точности общего расчета?

(Возможно, это поможет, если вы указали какой-либо более актуальный код. Единственный код, который вы указали, - 18/4.25, который не может быть фактическим выражением в вашем коде, поскольку второе число является double, и вы не можете присвоить результат этого выражения decimal без литья).


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

+0

ну, я думаю, это намного сложнее, чем i thoghot lol. Спасибо за информацию. я не показывал никакого кода, потому что я провел некоторое тестирование, и он работал с разными номерами, например 17 и даже 12.5. его все еще странно для меня, что я не могу это сделать, но теперь я знаю, почему. также, im kinda новичок в программировании, и я сделал это для удовольствия :) – samy

3

Расчеты с плавающей точкой неточны. Десятичные значения делают точность лучше, потому что они 128-битные, но они все еще являются числами с плавающей запятой.

Сравнение двух чисел с плавающей запятой не делается с ==, а:

static bool SameDecimal(decimal a, decimal b) 
{ 
    return Math.Abs(a-b) < 1e-10; 
} 

Этот метод позволит вам сравнить два десятичных знака (я предполагаю, что 1e-10 является достаточно малая разница для вас, она должна для повседневного использования).

+0

Если вы собираетесь это сделать, вы должны смотреть на соотношение, а не на разницу двух значений и сравнить коэффициент с 1. Если абсолютная разница отношения и 1 находится в пределах 1 -10, вы можете быть на что-то , Но 1e-20 и 2e-20 будут иметь абсолютную разность 1e-20, но по вашей метрике эти два значения равны. – andand

+0

@andand Неправильно всегда использовать один или другой. Каждый из них генерирует ложные срабатывания/ложные негативы в определенных ситуациях. Вам нужно знать, какие типы чисел вы, вероятно, должны знать, что может быть более точным. – Servy

+0

@Servy Ярмарка достаточно. Можете ли вы привести пример, когда мой подход дает ложное положительное или отрицательное значение, но он будет правильно работать для предлагаемого подхода zmbq? Мне сложно это сделать. – andand

Смежные вопросы