![]() |
Модераторы: Daevaorn |
![]() ![]() ![]() |
|
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
9999E+60 - 64 цифры. У Вас 16 short, 32 байт (полезные данные) в куче, плюс накладные расходы sizeof(super_int) - как я понял, ещё 32 байт, за счёт использования vector<>. Итого 64 байта, если без выравниваний.
У меня будет 214 бит - 7 unsigned, 28 байт (полезные данные). Накладные расходы: usecnt, alloc, length, p - 16 байт, из них 12 перед 28 байтами в куче (40 байт) + 4 байта на стеке. Второе число с тем же значением стоит 4 байта, вне зависимости от значения. Весь класс в одном заголовке - неплохо для тестирования. В рабочей программе, когда заголовок будет инклюдиться много раз (а полная версия класса будет длиннее тестовой), это существенное замедление работы. В предудущем сообщении исправил код на рабочий, добавил умножение и деление на обычное число и тестовый main(); Это сообщение отредактировал(а) math64 - 31.8.2012, 23:17 |
|||
|
||||
Нитонисе |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 917 Регистрация: 5.11.2009 Репутация: нет Всего: 2 |
Нет. У меня член класса вектор (пустой) занимает 32 байта. Этот размер я замерил функцией sizeof(). Поскольку там тип short int (2 байта), значит зарезервировано 16 ячеек. При заполнении 17-ой будет выделяться новая память, насколько я понимаю. Так вот до этого самого выделения новой памяти я в 32 байтах могу разместить огромадное число 9999E+60. У вас же, насколько я понял, истинное значение числа равняется сумме чисел из массива data. Один элемент массива (unsigned int) занимает 4 байта. В 32 байтах поместится 8 таких чисел. Каждое число максимально равно 4.3E+9, умножив на 8 получим максимальное значение вашего типа на 32 байтах - 34.4Е+9. То есть намного меньше чем у меня. Это не учитывая обслуживающие дополнительные члены (для хранения знака или длины массива). |
|||
|
||||
Нитонисе |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 917 Регистрация: 5.11.2009 Репутация: нет Всего: 2 |
Все таки идея с представлением чисел дробями имеет слабые перспективы, так как я что-то не представляю как такие числа возводить в дробную степень (звлечение квадратных, кубических корней).
|
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
такое представление чисел имеет свое название (не могу сходу вспомнить), есть математика для них и библиотечки попадались.. это я к тому что все это уже придумано и реализовано, гугль должен помочь.. |
|||
|
||||
Нитонисе |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 917 Регистрация: 5.11.2009 Репутация: нет Всего: 2 |
Да, но корень квадратный, например, из 3 не извлекается. Стало быть надо хранить корень (а в общем случае - дробную степень) просто как характеристику числа и использовать каким-то образом ее в вычислениях. Вырисовывается сложная задача. Это сообщение отредактировал(а) Нитонисе - 1.9.2012, 10:54 |
|||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
Извлечение квадратного корня:
Добавлено через 6 минут и 42 секунды А я сразу про подобное предупреждал. Большинство чисел - иррациональны и даже трасцендентны, и в копмьютере представляются только приближенно. Хотя некоторые, например, Пи, можно посчитать с любой заданной точностью. |
|||
|
||||
Нитонисе |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 917 Регистрация: 5.11.2009 Репутация: нет Всего: 2 |
ну то что его приближенно можно вычислить - это понятно. Но ведь вся идея была в том, чтобы вычисления были точными, поэтому приближенные методы не годятся. В начале темы говорили о библиотеке GMP, видимо это лучший способ реализовать высокую точность в расчетах? Хотел бы вернуться к названию темы. Где-то в первых постах говорили, что double не может повысить точность по сравнению с float. Но почему? Ведь double имеет точность 15 знаков, а float 7. То есть по идее от операций с double следует и точность бОльшую ожидать. Попутно возник вопрос. Если я где-то в вычислениях использовал разнотипные данные (например double умножаю или складываю с float), как это отразится на точности? При выполнении операции данные ведь преобразуются к одному типу. Вопрос - к какому? |
|||
|
||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
При умножении double на float, предварительно float преобразуется в double. Если float представлял число точно (например, 2.f) - результат будет с точностью double. Если нет - с точностью float. Использование double НЕ УМЕНЬШИТ точность вычислений - но в некоторых случаях не повысит. Тоже вычисление корня квадратного уравнения, близкого к 0 - использование double с традиционной формулой даст худший результат, чем вычисление другого корня в float и использование теоремы Виета. |
|||
|
||||
Нитонисе |
|
||||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 917 Регистрация: 5.11.2009 Репутация: нет Всего: 2 |
Допустим мне надо произвести высиления с точностью double. Как их правильно записать:
То есть хуже не будет, а скорее всего будет лучше, но не всегда? ![]() Но вот вы сразу опровергли предыдущее свое утверждение, показав, что в некоторых случаях double хуже float. Только не понятно почему? math64, вы предлагали использовать класс Approx для контроля погрешности. Я бы его немного преобразовал.
При всех математических операциях dv будет меняться. После длительных вычислений я получу некое dv с которым будет более менее удобно работать, выполняя логические действия. Например если v < dv - значит число равно нулю. Сравнивая числа, если fabs(n1.v-n2.v) < max(n1.dv,n2.dv), то числа равны. Только вот не совсем понимаю как мне этот параметр dv вычислять. Подскажите чему он будет равен при стандартных математических операциях (+, -, *, /), а также при возведении числа в дробную степень и применении тригонометрических функций? Это сообщение отредактировал(а) Нитонисе - 2.9.2012, 11:14 |
||||||
|
|||||||
Нитонисе |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 917 Регистрация: 5.11.2009 Репутация: нет Всего: 2 |
Да и еще подумал - что тольку от этого параметра dv, если он и сам вычисляется не точно, а с погрешностью...
|
|||
|
||||
FCM |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 461 Регистрация: 30.3.2009 Репутация: нет Всего: 9 |
Переход к double решает многие проблемы. Можешь проверить, написав свою программу через typedef-псевдоним, в качестве которого выбирать либо float, либо double.
(Есть еще 80-битные и 128-битные floating point, но без веских оснований не стоит заморачиваться.) Это сообщение отредактировал(а) FCM - 2.9.2012, 19:02 |
|||
|
||||
math64 |
|
||||||||||||||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
В результате получишь 0. 1 делится на 3 как целое число, результат = 0. Нужно
или
лучше чем
но хуже
а лучше всего
Ещё пример: Нужно посчитать 1 + 1/2 + 1/3 + ... 1/n; где 1/n - намного меньше "компьютерого эпсилон". Если будешь считать попорядку - начиная с какого-то члена добавление очередного слагаемого не будет изменять сумму, а ведь ряд расходится! А вот если начнёшь складывать с конца - получишь результат с приемлемой точностью даже с double, не прибегая к точному вычислению с помощью дробей из длинных чисел. Для контроля за погрешностью я предлагал два врианта: 1. (минимум, максимумум) - абсолютно точно известно, что число не вылезет за пределы диапазона. Но по мере вычисления диапазон часто быстро расширяется, в то время как чило имеет нормальное распределение с максимумом где-то в середине диапазона. Поэтому второй вариант: 2. (мат. ожидание, среднее квадратичное отклонение) С вероятностью 95% (если правильно помню тер.вер.) число находится диапазоне 3 СКО. Но всё таки всегда будет ненулевая вероятность, что число может оказаться равным 0. Это сообщение отредактировал(а) math64 - 2.9.2012, 20:24 |
||||||||||||||
|
|||||||||||||||
math64 |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 8 Всего: 72 |
Ну а подсчёт вероятности такой:
X = x + dx*nx; // nx - случайная величина нормального распределения СКО = 1, среднее = 0 Y = y + dy*ny; Считая, что dy и dy достаточно малы, Z = F(X,Y) = F(x,y) + dx*nx*dF/dx + dy*ny*dF/dy + ошибка вычислений. где dF/dx и dF/dy - частные производные и вычисляй СКО для dx*nx*dF/dx + dy*ny*dF/dy + ошибка вычислений, считая что ошибка вычислений - случайная величина с равномерным распределением (-eps*Z,eps*Z) Это сообщение отредактировал(а) math64 - 2.9.2012, 20:47 |
|||
|
||||
Нитонисе |
|
||||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 917 Регистрация: 5.11.2009 Репутация: нет Всего: 2 |
Похоже что так. Единственная для меня проблема здесь в логических операциях с double. Сравниваю так |a-b| < min. То есть если модуль разницы меньше некоего минимального числа, то a = b. Весь вопрос в том что выбрать за минимальное число. До сих пор работая с double я брал число 0.001. Для моих задач чаще всего хватало, но не всегда. Хотелось бы как-то обоснованней назначать его. Вот если бы параллельно основным вычислениям шел бы и расчет погрешности, то эту погрешность я бы и принимал в качестве минимальной разницы чисел. math64,
Это две эквивалентные записи? В первом случае ведь единица приводится к double неявно. Может она в вычислениях к float приведется? И почемы вы тройку не приводите к double? В операции деления она автоматически преобразуется в double, так как единица принадлежит этому типу? А что если не преобразуется? А если к double привести тройку, а единицу нет (1/(double)3) - то тройка преобразуется к int? Правильна ли ниже запись цикла, где надо считать с точностью double, но счетчик цикла типа int.
Так ведь и если с конца начать складывать, то до некоторого числа сумма будет равняться нулю.
|
||||||
|
|||||||
FCM |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 461 Регистрация: 30.3.2009 Репутация: нет Всего: 9 |
Если речь идет о сравнении в численных итеративных задачах - во многих случаях контролируют относительную точность и (на случай нулевого результата) абсолютную. (Все же посмотри первую главу Вержбицкого, насчет различных видов ошибок и методов их оценки) Это сообщение отредактировал(а) FCM - 3.9.2012, 07:54 |
|||
|
||||
![]() ![]() ![]() |
Правила форума "С++:Общие вопросы" | |
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |