Версия для печати темы

Нажмите сюда для просмотра этой темы в оригинальном формате

Форум Игры разума [braingames] _ Свободное общение _ Double в Си

Автор: рффшник 7.2.2008, 14:24

Я сам не программист, но для решения некоторых прикладных задач потребовалось изучить Си. И при решении одной из таких задач вылезла одна маленькая проблемка. Есть некоторая проверка истинности :

if ((выражение типа дабл)!=0){
нечто
}

но иногда выходит так, что выражение, которое должно быть равно нулю - равно некоторому очень маленькому числу, что приводит к ненужному выполнению условия (выражение типа дабл)!=0. Из-за этого программа работает не вполне корректно. Можно исправить проблему, если вместо проверки равенства сделать другую проверку:

if (fabs(выражение типа дабл)>x)

но встает вопрос, каким минимальным можно взять "х"? Эмпирически оно получается порядка 10^-14. Но у меня нет гарантий, что определенном стечении обтоятельств не потребуется, скажем, 10^-13.

Как быть, господа программисты?

ЗЫ если это важно: выражения типа дабл равно сумма квадратов n double чисел минус квадрат суммы n double чисел


Автор: nik_vic 7.2.2008, 15:08

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

Автор: рффшник 7.2.2008, 16:24

QUOTE(nik_vic @ 7.2.2008, 15:08) *

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


это, конечно, логично. В моей задаче достаточно будет взять 10^-10, это будет в пределах статистической погрешности измеренных величин. Но можно ли быть уверенным, что эти необходимые мне 10^-10 будут хорошо согласовываться с машинными вычислениями?! Хотелось бы знать, разве не существует некого конкретного числа, выше которого погрешность при операциях с числами double не получится? возможно, это конкретное число будет зависеть от конктреной системы - хз. Хотя есть ведь стандарт ANSI, а в нем вроде все системно независимо.

Автор: nik_vic 7.2.2008, 17:19

QUOTE(рффшник @ 7.2.2008, 16:24) *

Хотелось бы знать, разве не существует некого конкретного числа, выше которого погрешность при операциях с числами double не получится?

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


Автор: Mouse 7.2.2008, 17:38

QUOTE
Проблема стандартна и во всех языках решается одинаково - выбором этого х.

проблемма в операциях с потерей данных. всё зависит от того с какими числами работаете, и сколько операций происходит(и какие они, не помню как называются но операции +- - плохие */ - хорошие)

проблемма обычно возникает если числа несоразмерные т.е. отношение порядка длинны мантисы.
т.е. 1е300+1е250-1е300=0(в С++)

погрешности(относительная) операций типа +- = 1е-15*(разрядность_большего по_модулю-разрядность_меньшего_по_модулю)^10. т.е 1.???+1000.???? даст погрешность 1е-12

для сравнения положительных чисел типа сумма квадратов лучше использовать не обсолютную погрешность, а относительную.
т.е.
double m1=max(fabs(a),fabs(cool.gif),m2=min(fabs(a),fabs(cool.gif);
if(m2/m1>0.999999)то равны

QUOTE
Хотя есть ведь стандарт ANSI, а в нем вроде все системно независимо.

типы в С++ системо зависиммы
например long double в MS/Intel С++ это 8байт(15знаков мантиса), в Борланде 10(19знаков вроде), что странно т.к. 10байт это вроде родной для х86 тип.

Автор: Geen 7.2.2008, 17:58

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

Автор: рффшник 7.2.2008, 19:38

Mouse, спасибо!

Geen, о какой дисперсии и о каком флаге вы говорите? ниче не понял...

Автор: waldian 7.2.2008, 20:20

QUOTE(рффшник @ 7.2.2008, 19:38) *
Mouse, спасибо!

Geen, о какой дисперсии и о каком флаге вы говорите? ниче не понял...

Да просто выражение в написанном виде ни что иное как дисперсия набора из этих самых n чисел, а она равна 0 только если все числа равны.
Только сравнивать даблы на равенство просто так тоже нельзя smile.gif)

Автор: Geen 7.2.2008, 22:20

QUOTE(waldian @ 7.2.2008, 20:20) *

Да просто выражение в написанном виде ни что иное как дисперсия набора из этих самых n чисел, а она равна 0 только если все числа равны.
Только сравнивать даблы на равенство просто так тоже нельзя smile.gif)

Зато ошибка не накапливается smile.gif

Автор: рффшник 7.2.2008, 23:14

QUOTE(waldian @ 7.2.2008, 20:20) *

Да просто выражение в написанном виде ни что иное как дисперсия набора из этих самых n чисел, а она равна 0 только если все числа равны.



ах, вон оно что. Не сразу врубился о чем речь. В том выражении не хватает домножения на n квадрата суммы. Тогда это будет не дисперсия, а знаменатель выражения для определения одного из коэффициентов уравнения прямой методом МНКsmile.gif


а как даблы можно сравнивать?

Автор: Mouse 7.2.2008, 23:26

QUOTE
Да просто выражение в написанном виде ни что иное как дисперсия набора из этих самых n чисел, а она равна 0 только если все числа равны.

ввели в ступор.
для дисперсии в выражении вроде ещё одного N нехватает
иначе 1^2+1^2!=(1+1)^2

если дело в проверки дисперсия=0(все числа одинаковые) то правильно условие будет(max-min<"погрешность_приборов/компа")

double сравнивать на = нельзя. это основы компьютерных вычислений(забыл как у нас этот раздел был). правила там достаточно просты.
0. = считаеться как попадание в область(т.е. |x-y|<погрешность), и чаше всего относительную(типа различие в 6м знаке, т.е что-то типа |x-y|/(|x|+|y|)<1e-6)
1. */ на погрешность почти не влияют
2. + на ответ мало влияет, 1000000001 и 1000000000 можно сказать равно
3. - можно ожидать что угодно, как я привёл пример 10^250
4. ну и так далее, нам этот курс несколько недель читали smile.gif

Автор: рффшник 7.2.2008, 23:44

QUOTE(Mouse @ 7.2.2008, 23:26) *

double сравнивать на = нельзя. это основы компьютерных вычислений(забыл как у нас этот раздел был). правила там достаточно просты.
0. = считаеться как попадание в область(т.е. |x-y|<погрешность), и чаше всего относительную(типа различие в 6м знаке, т.е что-то типа |x-y|/(|x|+|y|)<1e-6)
1. */ на погрешность почти не влияют
2. + на ответ мало влияет, 1000000001 и 1000000000 можно сказать равно
3. - можно ожидать что угодно, как я привёл пример 10^250
4. ну и так далее, нам этот курс несколько недель читали smile.gif


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

Кстати, а вот эти слова:

QUOTE
погрешности(относительная) операций типа +- = 1е-15*(разрядность_большего по_модулю-разрядность_меньшего_по_модулю)^10. т.е 1.???+1000.???? даст погрешность 1е-12


означают, что А-В посчитается с погрешностью меньшей 1е-15, при 0<A,B<1?

Автор: Mouse 8.2.2008, 0:22

QUOTE
означают, что А-В посчитается с погрешностью меньшей 1е-15, при 0<A,B<1?

не меньшей, а сравнимой. т.е. ошибка будет где-то в 15м знаке после запятой, зависит от методов округления. берите 1е-14 при 0<A,B<1.(учитывайте что разрядность двоичная, т.е. гарантируемая точность операции это спецификация процессора/системы)

QUOTE
Сегодня с утра я еще и не задумывался, что равно может быть на самом деле и не очень то равно

сравните состояние милиордеров по версии различных источников(в одинаковое время), по теории равны, по разнице, бюджет малой(а может и несовсем) страны smile.gif

Автор: рффшник 8.2.2008, 0:45

QUOTE(Mouse @ 8.2.2008, 0:22) *


сравните состояние милиордеров по версии различных источников(в одинаковое время), по теории равны, по разнице, бюджет малой(а может и несовсем) страны smile.gif



самим этим миллиардерам, наверное, интересно наблюдать, с какой точностью другие считают их деньги biggrin.gif

Автор: рффшник 8.2.2008, 9:21

Господа, еще один вопрос: у меня есть дабл и я хочу на него посмотреть. Как сделать так, чтобы он выводил не первые N значащих знаков, а округлял с точностью до нного знака?

Автор: Geen 8.2.2008, 12:17

%.15g например

Автор: рффшник 11.2.2008, 18:25

QUOTE(Geen @ 8.2.2008, 12:17) *

%.15g например


ty!