![]() |
Модераторы: LSD, AntonSaburov |
![]() ![]() ![]() |
|
Aprol |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 259 Регистрация: 15.6.2007 Репутация: нет Всего: нет |
Первый фокус: Кусок кода
На тестовых данных k=10, h=2.29,xmin=3.6,xmax=26.5.Это достаточно, чтобы заполнить массив nvi Делим интервал [3.6;26.5] с шагом 2.29, значения подынтервалов записываются в nvi. По логике вещей значения должны быть следующими: 3,6 5,89 8,18 10,47 12,76 15,05 17,34 19,63 21,92 24,21 26,5 [0] = 3.6 [1] = 5.89 [2] = 8.18 [3] = 10.47 [4] = 12.76 [5] = 15.05 [6] = 17.34 [7] = 19.630001 [8] = 21.920002 [9] = 24.210003 [10] = 26.500004 Откуда эти хвосты в 7,8,910 элементах? Второе: mx=15.05
После присваивания получаем a_t= 15.050000190734863 Это откуда такой хвост? |
||||
|
|||||
LSD |
|
|||
![]() Leprechaun Software Developer ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 15718 Регистрация: 24.3.2004 Где: Dublin Репутация: 210 Всего: 538 |
Дело в том, что float и double хранятся как двоичная дробь, а ты оперируешь десятичными дробями. И проблема в том, что не всякая десятичная дробь может быть представлена как двоичная, приходится считать приближенно. Отсюда погрешность и берется. -------------------- Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it. |
|||
|
||||
Aprol |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 259 Регистрация: 15.6.2007 Репутация: нет Всего: нет |
Странно, такие простые вычисления, а уже погрешность...
как мне быть в такой ситуации? округлять? но по каким правилам, чтобы в других данных не обрубить мне ничего нужного
после присваивания a_t=15.05 как надо... что-то не догоняю... mx=15.05 откуда лаги... Это сообщение отредактировал(а) Aprol - 21.12.2009, 17:39 |
|||
|
||||
MaxPayneC |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 324 Регистрация: 18.2.2006 Репутация: 5 Всего: 9 |
LSD, не могли бы вы рассказать подробнее на тему двоичных и десятичных дробей, или дать ссылку где почитать?
|
|||
|
||||
LSD |
|
||||
![]() Leprechaun Software Developer ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 15718 Регистрация: 24.3.2004 Где: Dublin Репутация: 210 Всего: 538 |
Ну тут вопрос, в том что за вычисления ты делаешь. В принципе для расчетов с фиксированной точностью (n-знаков после запятой) хорошо подоходит BigDecimal, но у него один недостаток он медленно работает и требует много памяти (каждое вычисление создает новый объект). Еще есть такой класс Fraction он делает вычисления оперируя натуральными дробями, можешь попробовать его. Но вообще, надо побольше знать о задаче, чтобы посоветовать что-то конкретное.
Базовое это стандарт IEEE 754. Еще есть IEEE-754 Conversion Applet, который показывает как это число будет представлено в памяти. Ну и можешь в качестве упражнения на бумажке попробовать привести дробь 5/100 к основанию 2^x ![]() -------------------- Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it. |
||||
|
|||||
Aprol |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 259 Регистрация: 15.6.2007 Репутация: нет Всего: нет |
Да в данном случае задача простая разбить интервал с шагом на подинтервалы, что и делает в первом куске кода.
А вообще задача состоит в оптимизации значения аргументов функции, то бишь математическая задача, и там вот такие левые хвосты не нужны... потому то алгоритм и не работает. Результат не сходится с тем что посчитано в экселе. Это как? |
|||
|
||||
LSD |
|
|||
![]() Leprechaun Software Developer ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 15718 Регистрация: 24.3.2004 Где: Dublin Репутация: 210 Всего: 538 |
Когда ты складываешь два BigDecimal числа, то старые не меняются, а создается новый с результатом вычисления суммы. Возьми вместо float - double, выбери требуемую точность (скажем 6 знаков после запятой), и округляй после каждого шага. -------------------- Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it. |
|||
|
||||
MaxPayneC |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 324 Регистрация: 18.2.2006 Репутация: 5 Всего: 9 |
||||
|
||||
Aprol |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 259 Регистрация: 15.6.2007 Репутация: нет Всего: нет |
||||
|
||||
COVD |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1655 Регистрация: 26.7.2005 Репутация: 17 Всего: 43 |
Сравнивать результаты работы двух программ следует при одинаковым формате отображаемых данных. Например, если эксель отображает результаты расчета округляя до двух знаков после запятой, то и в другой программе следует применить аналогичный формат. |
|||
|
||||
Дрон |
|
||||||
![]() Java-ненавистник :) ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3179 Регистрация: 29.12.2002 Где: Санкт-Петербург Репутация: 6 Всего: 92 |
Не сочтите за наезд, но можно узнать сколько вам лет? И место учёбы? Вопросы про погрешности в float/double встречаются регулярно, я на них даже иногда подробно отвечаю. А тут вот любопытно стало, кто же их всё-таки задаёт? ![]() А насчёт округления... ну вот например до двух знаков после запятой:
Добавлено @ 19:06
Недавно уже в разделе .NET приводил пример. Считаем в уме: 1 / 3 = 0.3333(3) 1/3 * 3 = 1 0.3333(3) * 3 = 0.9999(9) ≠ 1 Вот и тут то же самое ![]() Это сообщение отредактировал(а) Дрон - 21.12.2009, 19:09 -------------------- Да. Именно так. |
||||||
|
|||||||
Aprol |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 259 Регистрация: 15.6.2007 Репутация: нет Всего: нет |
причем тут бесконечные дроби? когда результат вполне конкретен и равен он 15.05. Это можно ручками взять и посчитать ![]() Спасибо за пример, я нашел способ. ток мне кажется округляя мы только повышаем ошибку. Раньше она появлялась в меньших разрядах, а теперь мы поднимем ее до , скажем 10тысячных... Конфиденциальные данные не разглашаю. |
|||
|
||||
LSD |
|
|||
![]() Leprechaun Software Developer ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 15718 Регистрация: 24.3.2004 Где: Dublin Репутация: 210 Всего: 538 |
При том, что иногда дробь, можно выразить только бесконечной периодической или непериодической десятичной (доичной, троичной и т.д.) дробью. И это по идее проходят в школе ![]() -------------------- Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it. |
|||
|
||||
Дрон |
|
||||||
![]() Java-ненавистник :) ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3179 Регистрация: 29.12.2002 Где: Санкт-Петербург Репутация: 6 Всего: 92 |
Это в десятичных дробях он конкретен. Допустим 15.05 нормально представляется в float, но во время вычислений где-то появилось непредставимое число (считай что бесконечная дробь) и в итоге появилась погрешность. Я же пример с 1/3 не зря привёл -- результат вычислений (1 / 3) * 3 зависит от того, в какой системе мы считаем. Если считаем в обыкновенных дробях, то всё хорошо, если считаем в десятичных то есть погрешность. Попробуй ещё вариант:
У меня Java под рукой нет, но результат должен быть совсем не 0.
Не знаю. Не буду ничего утверждать, чтобы не вводить в заблуждение. Этому должны в институте учить... Меня учили, но давно ![]() Недавно, кстати, столкнулся с проблемой, что при суммировании большого количества чисел результат был близким к 0 (что-то вроде 1e-10) и, к моему удивлению, в зависимости от того, какой тип я использовал у меня получался разный знак результата, а он-то мне как раз и был нужен ![]() В Java нет встроенного типа decimal, как в C#, поэтому либо считать в double, либо в медленном BigDecimal, как сказал LSD. Только вот мне кажется, что в твоей задаче вполне должно хватать точности double. Да даже те результаты во float, которые ты пишешь вполне нормальны -- это ж последовательное приближение, оно не может быть точным... Не говоря уж о том, что в реальном мире исходные данные не бывают точными, а считать с большей точностью, чем есть в исходных данных -- бесполезно ![]() Ок, проехали ![]() -------------------- Да. Именно так. |
||||||
|
|||||||
serger |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 518 Регистрация: 19.6.2007 Где: Ижевск Репутация: 1 Всего: 5 |
Особенно если это деньги... ![]() -------------------- упс! |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Java" | |
|
Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Java: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |