С Новым годом! Форум программистов, компьютерный форум, киберфорум
Haskell
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.72/25: Рейтинг темы: голосов - 25, средняя оценка - 4.72
17 / 7 / 0
Регистрация: 20.08.2012
Сообщений: 51

Точность действительных чисел

14.10.2012, 13:22. Показов 4920. Ответов 22
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Написав функцию численного интегрирования...

Haskell
1
2
3
4
5
6
7
8
9
integral :: (Enum a, RealFrac a) => (a -> a) -> (a, a) -> a -> a
integral f (a, b) dx | a > b = error "First point bigger as last!"
        | a == b = 0
        | dx > (b - a) = error "Points interval is too big!"
        | dx <= 0 = error "Points interval is not positive!"
        | otherwise = sum $ zipWith (\x y -> (x + y) * dx / 2) firsts seconds
    where
        firsts = [f x | x <- [a, a + dx .. b], x < b]
        seconds = (tail firsts) ++ [f b]
Я обнаружил следующий неприятный побочный эффект: в действительных числах вычисления неточны.

То есть, вычисляя...

Haskell
1
integral (\x -> 1) (1, 2) 0.1
Я получаю не 1, как должно было быть, а 0.9999999999999999

Как это скорректировать?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
14.10.2012, 13:22
Ответы с готовыми решениями:

Список действительных чисел
Почему хаскел строит такой список? Просто особенность отображения или баг? (странным образом сожрались теги)...

Дано 8 действительных чисел. Вычислить сумму квадратов разностей корней из модулей действительных чисел
Дано 8 действительных чисел. Вычислить сумму квадратов разностей корней из модулей действительных чисел.

Вычислить сумму с точность до e. Точность достигается, когда очередное слагаемое получается <= e
Вычислить сумму с точность до e. Точность достигается, когда очередное слагаемое получается &lt;= e. S=1+(1/(1*2))...

22
 Аватар для Сtrl
144 / 134 / 8
Регистрация: 19.07.2011
Сообщений: 184
14.10.2012, 14:25
Се есть особенность вычислений с плавающей точкой, которая от языка не зависит. Выход - отказаться от Float и представлять дробные числа в виде, например, отношения целых (модуль Data.Ratio).
1
17 / 7 / 0
Регистрация: 20.08.2012
Сообщений: 51
14.10.2012, 15:02  [ТС]
Ну это, как бы, ограничение общности.
0
Эксперт функциональных языков программированияЭксперт по математике/физике
4312 / 2104 / 431
Регистрация: 19.07.2009
Сообщений: 3,204
Записей в блоге: 24
14.10.2012, 15:41
Цитата Сообщение от flammberg Посмотреть сообщение
Ну это, как бы, ограничение общности.
Да нет, по-другому не получится.

Если не веришь, напиши функцию, сравнивающую два действительных (в нашем обычном понимании) числа за конечное время. Или проще: попробуй определить, а что же вообще из себя представляет действительное число.
0
17 / 7 / 0
Регистрация: 20.08.2012
Сообщений: 51
14.10.2012, 15:48  [ТС]
Цитата Сообщение от Mysterious Light Посмотреть сообщение
Или проще: попробуй определить, а что же вообще из себя представляет действительное число.
Хм... Действительные числа - объединение множества рациональных и иррациональных чисел. Или что вы имеете в виду?
0
Эксперт функциональных языков программированияЭксперт по математике/физике
4312 / 2104 / 431
Регистрация: 19.07.2009
Сообщений: 3,204
Записей в блоге: 24
14.10.2012, 16:28
У нас на матане действительные числа вводились как целое число + бесконечная последовательность цифр 0..9. Потом мы ввели понятие равенства:
https://www.cyberforum.ru/cgi-bin/latex.cgi?x=y \; =\limits^{\textrm{def}} \; \forall |(x)_n-(y)_n| \leq 10^{-n}
где (x)n — рациональное число, получаемое путём "отрезания" всех чисел с n после запятой.
Далее мы перешли к фактормножетву, то есть отождествили +0 и -0, 0.99... и 1.00... и так далее. Была ещё теорема, что двоякое представление возможно, только если с некоторого момента начинаются только нули или только девятки.

Так было в матане, где многое доказывалось от противного (пример: доказательство несчётности R).

Было другое определение R, как топологического пополнения Q.

Далее я могу немного приврать, поэтому к дальнейшему стоит относиться с осторожностью.

В книге Гейтинга «Интуиционизм» в главе 2.2, посвященной дейтсвительным числам, вводится другое определение числа, которое, вообще говоря, отличается от первого. Понятие числа вводится как генератор действ. чисел, то есть последовательность рациональных чисел, фундаментальную в смысле Коши. Это определение похоже на второе определение (пополнение Q), только здесь все утверждение должны быть конструктивными.

Имея последовательности (x,y :: [a]), вы никогда не напишите функцию, за конечное время определяющую, равны ли x и y. Вы также никогда не напишите функцию, имеющую тип
Haskell
1
:: ((p -> q) -> p) -> p
Вывод: хаскелль не умеет работать с задачами, требующими неконструктивного (или неинтуиционисткого, я точно не знаю) подхода. Поэтому работать с действ. числами в рамках определения числовых генераторов можно, но непрактично, а как-либо по-другому вообще невозможно.
Поэтому Ctrl и предложил Вам использовать Ratio.
0
Супер-модератор
Эксперт функциональных языков программированияЭксперт Python
 Аватар для Catstail
38167 / 21102 / 4307
Регистрация: 12.02.2012
Сообщений: 34,690
Записей в блоге: 14
14.10.2012, 16:31
Действительное число - это (в общем случае) множество всех десятичных дробей (включая, конечные, периодические и непериодические). Компьютерное вещественное - это не математическое вещественное (т.к. в мантиссе конечных размеров нельзя разместить даже периодическую дробь). Непонимание этой разницы приводит к неприятным сюрпризам.

Например, составьте программу вычисления синуса разложением в ряд с заданной точностью. А потом попробуйте посчитать знач. синуса при x=10, 20, 100, 1000, 1000 и т.д. И увидите, что при малых значениях аргумента точность будет очень хорошей, а при больших синус окажется больше единицы. Причина - накопление погрешности.

Добавлено через 2 минуты
Цитата Сообщение от Mysterious Light Посмотреть сообщение
хаскелль не умеет работать с задачами
- подозреваю, что "виноват" не Хаскел, а Intel
0
Эксперт функциональных языков программированияЭксперт по математике/физике
4312 / 2104 / 431
Регистрация: 19.07.2009
Сообщений: 3,204
Записей в блоге: 24
14.10.2012, 16:46
Цитата Сообщение от Catstail Посмотреть сообщение
подозреваю, что "виноват" не Хаскел, а Intel

Не по теме:

Intel как раз не виноват. Он делает то, что он делает (простите капитанство)
Здесь фундаментальная проблема: а можем ли мы вообще что-то анализировать, требующее для вычисления счётного (или даже несчётного) числа действий.
В классике мы можем идти от противного, сводить к абсурду, применять закон двойного отрицания или закон Пирса. Собственно, чтоб утверждать, что уравнение
https://www.cyberforum.ru/cgi-bin/latex.cgi?8x^8+7x^7+6x^6+5x^5+4x^4+3x^3+2x^2+x+100500=0
имеет ровно 8 комплексных корней, то есть не более 8 действительных, нам не обязательно эти корни явно получить.
Такой подход пока невозможен в целом для программ, заточенных под Машину Тьюринга (или другой подобный исполнитель).
Разве что только не научим компьютер «мыслить», как человек, который говорит об объектах, даже не задумываясь о том, что эти объекты ему неизвестны. Да, велик человек в своей противоречивости.

0
17 / 7 / 0
Регистрация: 20.08.2012
Сообщений: 51
14.10.2012, 17:14  [ТС]
Mysterious Light, это все конечно очень мило, но как уже заметил выше Catstail, компьютерное вещественное число - всего лишь симуляция математического вещественного с максимально возможным правдоподобием. Разумеется, я понимаю, что округление при рассчетах в числах с плавающей точкой неизбежны, но не до такой же степени!

В моем тестовом примере рассчеты идут с точностью до 0.1. Уверяю вас, какой-нибудь вшивый РНР, в данной задаче, выдаст абсолютно правильный результат. Я все же склонен полагать, что виноват именно Хаскел.
0
Супер-модератор
Эксперт функциональных языков программированияЭксперт Python
 Аватар для Catstail
38167 / 21102 / 4307
Регистрация: 12.02.2012
Сообщений: 34,690
Записей в блоге: 14
14.10.2012, 17:21
Цитата Сообщение от flammberg Посмотреть сообщение
Уверяю вас, какой-нибудь вшивый РНР, в данной задаче, выдаст абсолютно правильный результат.
- давайте проверим! Вы интегрировали функцию f(x)=1 на отрезке [0,1]?
0
17 / 7 / 0
Регистрация: 20.08.2012
Сообщений: 51
14.10.2012, 17:49  [ТС]
Пожалуйста. Вот функциональность, копирующая мой пример на Хаскеле...

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
 
function cnt1($x)
{
    return 1;
}
 
function integral($method, $a, $b, $dx)
{
    $x=$a;
    $s=0;
 
    while ( $x<$b )
    {
         $y=($x+$dx)>$b?$b:$x+$dx;
         $s+=($method($x)+$method($y))*$dx/2;
         $x+=$dx;
    }
 
    return $s;
}
 
$s=integral("cnt1", 1, 2, 0.1);
print($s);
Возвращает четко единицу.
0
~ Эврика! ~
 Аватар для OhMyGodSoLong
1258 / 1007 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
14.10.2012, 18:18
Цитата Сообщение от flammberg Посмотреть сообщение
Возвращает четко единицу.
Нет уж, давайте по-честному:
- print $s;
+ print number_format($s, 17);
0
14.10.2012, 18:36

Не по теме:

А я думал это ошибка пентиумов, связанная с ошибочным переводом двоичного числа в десятичное и наоборот.

пример:

0.1 переходит в 0.00011001100110011...



Не по теме:

Да, я это сообщение жёстко заредактировал.

0
Эксперт С++
 Аватар для Nameless One
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
14.10.2012, 18:39
На самом деле, это вполне ожидаемый результат, связанный с неточностью представления чисел с плавающей точкой и с ошибками арифметических операций над ними. Такой же результат должен быть получен во всех языках, в которых действительные числа реализованы в соответствии со стандартом IEEE 754. То есть почти во всех существующих ЯП.
1
17 / 7 / 0
Регистрация: 20.08.2012
Сообщений: 51
14.10.2012, 18:42  [ТС]
Цитата Сообщение от ~OhMyGodSoLong~ Посмотреть сообщение
Нет уж, давайте по-честному:
- print $s;
+ print number_format($s, 17);
Меня вообще-то интересует результат, а не честность соревнования.
0
14.10.2012, 18:45

Не по теме:

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



Не по теме:

Про честность... это в пхп у автора округляется результат что-ли?

0
Эксперт С++
 Аватар для Nameless One
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
14.10.2012, 18:49
flammberg, ну так замечание ~OhMyGodSoLong~ тут как раз к месту. print в первом случае выводит округленный результат, а при форматировании уже получаются честные 0.99999999999999989.

А вариант без форматирования аналогичен хаскельному:

Haskell
1
2
3
> printf "%.10f\n" $ integral (const 1) (1, 2) 0.1
1.0000000000
>
где спецификатор точности можно свободно менять от 0 до 15.
0
~ Эврика! ~
 Аватар для OhMyGodSoLong
1258 / 1007 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
14.10.2012, 18:49
Цитата Сообщение от flammberg Посмотреть сообщение
Меня вообще-то интересует результат, а не честность соревнования.
Это половые проблемы формата IEEE 754 (который может представить 1.0 точно, но надо очень постараться, чтобы получить это число в результате вычислений) и выводилки "по умолчанию" чисел в этом формате у Хаскелла, которая почему-то округляет числа до 16 значащих цифр, но к нулю, а не к ближайшему числу. Просто выводилка по умолчанию у PHP округляет к ближайшему, потому и получается 1.0.
1
Эксперт С++
 Аватар для Nameless One
5828 / 3479 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
14.10.2012, 19:01
А вообще, обычно ошибки в вычислениях с плавающей точной настолько малы, что на них вполне спокойно можно забить (если, конечно, мы не занимаемся денежными расчетами или управлением АЭС). В противном случае используем рациональные числа или числа с фиксированной точкой.
0
14.10.2012, 19:26

Не по теме:

Nameless One, так и представил:

<<---Слыш это, у миня программа насчитала 99.9999999, так что гони мне 9.999999406318238e-8 рублей сдачи!1!!1!>>.

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
14.10.2012, 19:26
Помогаю со студенческими работами здесь

Вычислить сумму с точность до e. Точность достигается, когда очередное слагаемое получается <= e
Вычислить сумму с точность до e. Точность достигается, когда очередное слагаемое получается &lt;= e.

Оператор Until. Вычислить сумму с точность до e. Точность достигается, когда очередное слагаемое получается <= e
Оператор Until. Вычислить сумму с точность до e. Точность достигается, когда очередное слагаемое получается &lt;= e

Точность передачи чисел из Аксесс в Ворд
Здравствуйте! Я недавно столкнулся с проблемой точности числовых значений в Access. Word, рассылки. При передаче чисел с двумя знаками...

В заданном массиве из 5 действительных чисел определите количество чисел, не попадающих в интервал от -1 до 1.
В заданном массиве из 5 действительных чисел определите количество чисел, не попадающих в интервал от -1 до 1.

Дано 10 действительных чисел. Определить количество, сумму и произведение отрицательных чисел
Дано 10 действительных чисел. Определить количество, сумму и произведение отрицательных чисел.


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru