Документация
По умолчанию, MATLAB ® использование 16 цифр точности. Для более высокой точности используйте vpa функция в Symbolic Math Toolbox™. vpa обеспечивает переменную точность, которая может быть увеличена без предела.
Когда вы выбираете арифметику переменной точности, по умолчанию, vpa использование 32 значительных десятичных цифры точности. Для получения дополнительной информации смотрите, Выбирают Numeric or Symbolic Arithmetic. Можно установить более высокую точность при помощи digits функция.
Аппроксимируйте сумму с помощью точности по умолчанию 32 цифр. Если по крайней мере один вход перенесен с vpa , все другие входные параметры преобразованы в переменную точность автоматически.
vpa(1/3) + 1/2
ans = 0.83333333333333333333333333333333
Необходимо перенести все внутренние входные параметры с vpa , такой как exp(vpa(200)) . В противном случае входные параметры автоматически преобразованы, чтобы удвоиться MATLAB.
Увеличьте точность до 50 цифры при помощи digits и сохраните старое значение digits в digitsOld . Повторите сумму.
digitsOld = digits(50); sum50 = vpa(1/3) + 1/2
sum50 = 0.83333333333333333333333333333333333333333333333333
Восстановите старое значение цифр для дальнейших вычислений.
digits(digitsOld)
Примечание
vpa выход является символьным. Чтобы использовать символьный выход с функцией MATLAB, которая не принимает символьные значения, преобразуйте символьные значения в двойную точность при помощи double .
Проверяйте ток digits установка путем вызова digits .
digits
Digits = 32
Измените точность для сингла vpa вызов путем определения точности как второго входа к vpa . Этот вызов не влияет digits . Например, аппроксимированный pi с 100 цифры.
vpa(pi,100)
ans = 3.14159265358979323846264338327950288419716939937510582097494 4592307816406286208998628034825342117068
digits % digits remains 32
Digits = 32
Переменная точность может быть увеличена произвольно. Найдите pi к 500 цифры.
digitsOld = digits(500); vpa(pi) digits(digitsOld)
ans = 3.1415926535897932384626433832795028841971693993751058209749 445923078164062862089986280348253421170679821480865132823066 470938446095505822317253594081284811174502841027019385211055 596446229489549303819644288109756659334461284756482337867831 652712019091456485669234603486104543266482133936072602491412 737245870066063155881748815209209628292540917153643678925903 600113305305488204665213841469519415116094330572703657595919 530921861173819326117931051185480744623799627495673518857527 248912279381830119491
digits и vpa управляйте количеством значительных десятичных цифр. Например, аппроксимация 1/111 с четырехразрядной точностью возвращает шесть цифр после десятичной точки, потому что первые две цифры являются нулями.
vpa(1/111,4)
ans = 0.009009
Примечание
Если вы хотите увеличить эффективность путем уменьшения точности, смотрите Скорость Увеличения путем Сокращения Точности.
Документация Symbolic Math Toolbox
Поддержка
- MATLAB Answers
- Помощь в установке
- Отчеты об ошибках
- Требования к продукту
- Загрузка программного обеспечения
© 1994-2021 The MathWorks, Inc.
- Условия использования
- Патенты
- Торговые марки
- Список благодарностей
Для просмотра документации необходимо авторизоваться на сайте
Войти
Памятка переводчика
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста — например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.
Как увеличить точность double C++?
Пытаюсь сделать одинаковое вычисление с помощью C++ чтобы точность была как в языке Ruby, однако C++ жестче округляет значения а делать round() для каждого прохода не вариант так как чисел после запятой может быть от 1 до 16, что посоветуете?
a = 3.2 b = 4.2 p = 8.3 puts ((a+b) * (p / 100)) # 0.6142000000000001
#include #include using namespace std; int main(void) < long double a = 3.2; long double b = 4.2; long double p = 8.3; cout
a = 9.809999999999999 b = 11.1 p = 8.3 puts ((a+b) * (p / 100)) # 1.7355299999999998
#include #include using namespace std; int main(void) < long double a = 9.809999999999999; long double b = 11.1; long double p = 8.3; cout
- Вопрос задан более трёх лет назад
- 5684 просмотра
Комментировать
Решения вопроса 0
Ответы на вопрос 1

Data Science
Не совсем корректно поставлен вопрос, тем что тебе нужно - ты понижаешь точность.
У float 23 мантисы, у double 52. Теоритически дабл имеет двухкратную точность в сравнении с float.
C++ жестче округляет значения
Это как понимать?
У тебя может быть до 16 чисел после запятой - это уже сильно округленно. Поставь себе конкретно вопрос - сколько именно чисел после запятой ты хочешь видеть в итоге? На столько и округляй.
Если же отвечать конкретно на формулировку твоего вопроса, а именно "как повысить точность", то 1 из ответов был бы long double
Точность и точность в вычислениях с плавающей запятой
Существует множество ситуаций, в которых точность, округления и точность в вычислениях с плавающей запятой могут работать для создания неожиданных для программиста результатов. Они должны соответствовать четырем общим правилам:
- При вычислении с одиночной и двойной точностью результат обычно не будет более точным, чем одна точность. Если требуется двойная точность, убедитесь, что все термины в вычислении, включая константы, указаны с двойной точностью.
- Никогда не следует предполагать, что на компьютере точно представлено простое числовое значение. Большинство значений с плавающей запятой не могут быть точно представлены как конечное двоичное значение. Например, .1 .0001100110011. в двоичном формате (он повторяется навсегда), поэтому его нельзя представить с полной точностью на компьютере с помощью двоичной арифметики, которая включает все компьютеры.
- Никогда не следует предполагать, что результат является точным для последнего десятичного разряда. Между ответом true и тем, что можно вычислить с конечной точностью любой единицы обработки с плавающей запятой, всегда существуют небольшие различия.
- Никогда не сравнивайте два значения с плавающей запятой, чтобы узнать, равны они или нет. Это является следствием правила 3. Почти всегда будут небольшие различия между числами, которые должны быть равными. Вместо этого всегда проверяйте, равны ли числа. Другими словами, проверьте, является ли разница между ними небольшой или незначительной.
Дополнительная информация
Как правило, описанные выше правила применяются ко всем языкам, включая C, C++и ассемблер. В приведенных ниже примерах демонстрируются некоторые правила, использующие POWERStation ДЛЯ ИНСТРУКЦИЙ ПО. Все примеры были скомпилированы с помощью ИНСТРУКЦИИ ПО POWERSTATION 32 без каких-либо параметров, за исключением последнего, написанного на языке C.
Пример 1
В первом примере показаны две вещи:
- По умолчанию константы FORTRAN имеют единую точность (константы C по умолчанию имеют двойную точность).
- Вычисления, содержащие любые термины одиночной точности, не намного более точны, чем вычисления, в которых все термины являются одиночной точностью.
После инициализации с использованием 1.1 (одна константа точности) y является неточной, как одна переменная точности.
x = 1.100000000000000 y = 1.100000023841858
Результат умножения значения одиночной точности на точное значение двойной точности почти так же плохо, как умножение двух одноточных значений. Оба вычисления имеют в тысячах раз больше ошибок, чем умножение двух значений двойной точности.
true = 1.320000000000000 (multiplying 2 double precision values) y = 1.320000052452087 (multiplying a double and a single) z = 1.320000081062318 (multiplying 2 single precision values)
Пример кода
C Compile options: none real*8 x,y,z x = 1.1D0 y = 1.1 print *, 'x =',x, 'y =', y y = 1.2 * x z = 1.2 * 1.1 print *, x, y, z end
Пример 2
В примере 2 используется четырехугольное уравнение. Он демонстрирует, что даже вычисления двойной точности не являются идеальными и что результат вычисления должен быть протестен, прежде чем он будет зависеть от того, могут ли небольшие ошибки иметь значительные результаты. Входные данные для квадратной корневой функции в примере 2 немного отрицательны, но по-прежнему недопустимы. Если вычисления двойной точности не имеют незначительных ошибок, результат будет следующим:
Root = -1.1500000000
Вместо этого он создает следующую ошибку:
- sqrt: ошибка ДОМЕНА
Пример кода
C Compile options: none real*8 a,b,c,x,y a=1.0D0 b=2.3D0 c=1.322D0 x = b**2 y = 4*a*c print *,x,y,x-y print "(' Root =',F16.10)",(-b+dsqrt(x-y))/(2*a) end
Пример 3
В примере 3 показано, что из-за оптимизации, которая выполняется, даже если оптимизация не включена, значения могут временно сохранять более высокую точность, чем ожидалось, и что не рекомендуется тестировать два значения с плавающей запятой на равенство.
В этом примере два значения равны и не равны. На первом этапе ЕСЛИ значение Z по-прежнему находится в стеке сопроцессора и имеет ту же точность, что и Y. Поэтому X не равен Y, и выводится первое сообщение. Во время второго запроса IF Z необходимо было загрузить из памяти и, следовательно, иметь ту же точность и значение, что и X, а второе сообщение также выводится на печать.
Пример кода
C Compile options: none real*8 y y=27.1024D0 x=27.1024 z=y if (x.ne.z) then print *,'X does not equal Z' end if if (x.eq.z) then print *,'X equals Z' end if end
Пример 4
Первая часть примера кода 4 вычисляет наименьшую возможную разницу между двумя числами, близкими к 1,0. Для этого в двоичное представление 1.0 добавляется один бит.
x = 1.00000000000000000 (one bit more than 1.0) y = 1.00000000000000000 (exactly 1.0) x-y = .00000000000000022 (smallest possible difference)
В некоторых версиях инструкции FORTRAN числа округляются при их отображении таким образом, чтобы неописуемое числовое выражение не было настолько очевидным. Именно поэтому при отображении x и y выглядят одинаково.
Вторая часть примера кода 4 вычисляет наименьшую возможную разницу между двумя числами, близкими к 10,0. Это также делается путем добавления одного бита в двоичное представление 10.0. Обратите внимание, что разница между числами вблизи 10 больше, чем разница около 1. Это демонстрирует общий принцип того, что чем больше абсолютное значение числа, тем точнее оно может храниться в заданном количестве битов.
x = 10.00000000000000000 (one bit more than 10.0) y = 10.00000000000000000 (exactly 10.0) x-y = .00000000000000178
Двоичное представление этих чисел также отображается, чтобы показать, что они различаются только на 1 бит.
x = 4024000000000001 Hex y = 4024000000000000 Hex
Последняя часть примера кода 4 показывает, что простые не повторяющиеся десятичные значения часто могут быть представлены в двоичном формате только повторяющейся дробной частью. В этом случае x=1.05, для которого требуется повторяющийся коэффициент CCCCCC. (Шестнадцатеричная) в мантиссе. В инструкции FORTRAN последняя цифра "C" округляется до "D", чтобы обеспечить наивысшую точностью:
x = 3FF0CCCCCCCCCCCD (Hex representation of 1.05D0)
Даже после округления результат не является полностью точным. После наименее значащих цифр возникает ошибка, которую можно увидеть, удалив первую цифру.
x-1 = .05000000000000004
Пример кода
C Compile options: none IMPLICIT real*8 (A-Z) integer*4 i(2) real*8 x,y equivalence (i(1),x) x=1. y=x i(1)=i(1)+1 print "(1x,'x =',F20.17,' y=',f20.17)", x,y print "(1x,'x-y=',F20.17)", x-y print * x=10. y=x i(1)=i(1)+1 print "(1x,'x =',F20.17,' y=',f20.17)", x,y print "(1x,'x-y=',F20.17)", x-y print * print "(1x,'x =',Z16,' Hex y=',Z16,' Hex')", x,y print * x=1.05D0 print "(1x,'x =',F20.17)", x print "(1x,'x =',Z16,' Hex')", x x=x-1 print "(1x,'x-1=',F20.17)", x print * end
Пример 5
В C плавающие константы по умолчанию удвояются. Используйте "f", чтобы указать значение с плавающей точкой, как в "89,95f".
/* Compile options needed: none */ #include void main() < float floatvar; double doublevar; /* Print double constant. */ printf("89.95 = %f\n", 89.95); // 89.95 = 89.950000 /* Printf float constant */ printf("89.95 = %f\n", 89.95F); // 89.95 = 89.949997 /*** Use double constant. ***/ floatvar = 89.95; doublevar = 89.95; printf("89.95 = %f\n", floatvar); // 89.95 = 89.949997 printf("89.95 = %lf\n", doublevar); // 89.95 = 89.950000 /*** Use float constant. ***/ floatvar = 89.95f; doublevar = 89.95f; printf("89.95 = %f\n", floatvar); // 89.95 = 89.949997 printf("89.95 = %lf\n", doublevar); // 89.95 = 89.949997 >
Обратная связь
Были ли сведения на этой странице полезными?
Проблема точности вычислений в методе вариации фазы Текст научной статьи по специальности «Математика»
Аннотация научной статьи по математике, автор научной работы — Дмитриенко Р. М., Емельянов А. А., Золотов С. А., Климашов В. Ю., Савихин С. А.
Описаны методы повышения точности и уменьшения погрешности вычислений в применении к задаче поиска корней уравнения при помощи вариации фазы, также оценивается эффективность применения графических процессоров при использовании данного метода.
i Надоели баннеры? Вы всегда можете отключить рекламу.
Похожие темы научных работ по математике , автор научной работы — Дмитриенко Р. М., Емельянов А. А., Золотов С. А., Климашов В. Ю., Савихин С. А.
Использование вычислений с мантиссой переменной длины для решения задачи оценки параметров систем
Арифметика многократной точности на основе систем остаточных классов
Метод умножения с масштабированием результата для высокоточных модулярно- позиционных интервально-логарифмических вычислений
Особенности представления вещественных чисел в постбинарных форматах
Модулярно-позиционный формат и программный пакет для разряднопараллельных вычислений высокой точности в формате с плавающей точкой
i Не можете найти то, что вам нужно? Попробуйте сервис подбора литературы.
i Надоели баннеры? Вы всегда можете отключить рекламу.
THE PROBLEM OF THE COMPUTING PRECISION OF THE PHASE VARIATION METHOD
This paper describes methods of precision improvement and computing error reduction as applied to the problem of phase variation-based equation roots solving. Estimations for the performance of GPU-based implementations of this method are given in the paper as well.
Текст научной работы на тему «Проблема точности вычислений в методе вариации фазы»
ИНФОРМАТИКА И СИСТЕМЫ УПРАВЛЕНИЯ
1 2 2 1 Р.М. Дмитриенко , А.А. Емельянов , С.А. Золотов , В.Ю. Климашов ,
С.А. Савихин1, А.Б. Терентьев2
ПРОБЛЕМА ТОЧНОСТИ ВЫЧИСЛЕНИЙ В МЕТОДЕ ВАРИАЦИИ ФАЗЫ
ФГНУ «Научно-исследовательский радиофизический институт»1, ООО «Научно-исследовательский центр специальных вычислительных технологий»
Описаны методы повышения точности и уменьшения погрешности вычислений в применении к задаче поиска корней уравнения при помощи вариации фазы, также оценивается эффективность применения графических процессоров при использовании данного метода.
Ключевые слова: численные методы, вариация, логарифмический вычет, мантисса, точность.
В последнее время, в связи с постоянным ростом производительности компьютеров, все чаще поднимаются вопросы о достоверности и надежности компьютерных вычислений. Основной недостаток арифметики с плавающей точкой состоит в том, что фиксируется только относительная ошибка округления. Этот недостаток может привести к потере точности и получению заведомо ложных результатов, например, при суммировании рядов. В случаях, когда ошибки в исходных данных и ошибки округления оказывают сильное влияние на результат вычислений, например, при решении плохо обусловленных систем уравнений, целесообразно вести расчеты с повышенной точностью.
Постановка задачи поиска комплексного корня уравнения
Одним из показательных примеров задач, для которых требуется повышенная точность вычислений и минимизация погрешности, является численное решение уравнений. Рассмотрим задачу нахождения комплексных корней произвольного уравнения
с помощью метода вариации фазы.
Будем считать, что функция f (z) является аналитической внутри некоторой замкнутой области S за исключением конечного числа изолированных особых точек и непрерывна вплоть до границы этой области. Из теории комплексного анализа известно, что разность между полным числом нулей N и полюсов P функции f (z) в области S вычисляется с помощью логарифмического вычета:
N - P = — f^^di, 2* i \f (О
где интегрирование ведется в положительном направлении (против часовой стрелки) по за-
© Дмитриенко Р.М., Емельянов А.А., Золотов С.А., Климашов В.Ю., Савихин С.А., Терентьев А.Б., 2011.
мкнутому спрямляемому контуру Ь, который ограничивает область 5. С другой стороны, известно, что логарифмический вычет функции равен вариации аргумента данной функции, подсчитанной вдоль контура Ь, то есть
На практике применима именно вторая формула. Предполагаем, что нам известны полюса функции / (г) с их кратностями, тогда по числу полных оборотов годографа исходного контура Ь вокруг начала координат можно найти число нулей внутри контура Ь. Основная проблема заключается как раз в определении числа полных оборотов, так как годограф в малой окрестности нуля может вести себя довольно сложным образом.
На рис. 1 показан пример кривой, в которую может перейти прямоугольный контур. По внешнему виду трудно подсчитать все ветки полученной кривой в окрестности нуля: изначально приближаясь к началу координат по спирали, она затем резко уходит в сторону.
Проблема детального исследования поведения годографа может быть решена увеличением шага разбиения исходного контура и повышением точности вычислений.
Авторами предложено два способа повышения точности и уменьшения погрешности, которые были применены к данной задаче. Эксперименты проводились с использованием графических процессоров, и далее будет представлено сравнение эффективности использования CPU и GPU. Но прежде чем переходить к описанию названных методов, целесообразно указать основы представления чисел с плавающей точкой.
В памяти компьютера числа с плавающей точкой представляются последовательным набором битов в следующем формате:
Под знак отводится один бит (0 — число положительное, 1 — число отрицательное).
Рис. 1. Пример годографа прямоугольного контура
Числа с плавающей точкой
| знак | показатель степени | мантисса |
Показатель степени и мантисса имеют фиксированный размер, поэтому диапазон представи-мых в данном формате чисел ограничен. Следовательно, существует наименьшее и наибольшее представимое число. Для формата double эти числа 10-308 и 10308 соответственно. Так как мантисса и показатель степени содержат только определенное количество значащих цифр, то, например, при сложении двух чисел, порядки которых сильно отличаются, можно получить неверный результат.
Рассмотрим пример. Пусть мантисса содержит три значащих цифры, а показатель степени - одну. Тогда при сложении двух чисел 1.23 * 103 и 3.45 * 10-2 получим
1.23 * 103 + 3.45 * 10-2 = 1230 + 0.0345 = 1230.0345 = 1.23 * 103,
что неверно. К настоящему моменту существует несколько библиотек для вычислений с повышенной точностью, например, GNU Multi-Precision Library (C++), ARPREC (C++/Fortran). Но все они не получили широкого распространения, так как время, затраченное на расчет с их помощью, в несколько раз превышает время расчета в формате double. Но сегодня этот недостаток можно компенсировать, если вести вычисления на графических процессорах, так как они существенно превосходят по производительности центральные процессоры, при большом объеме данных.
Переходим к описанию способов повышения точности и уменьшения погрешности. Первый способ заключается в эмуляции повышенной точности путем увеличения разрядности мантиссы и показателя степени. Смысл второго способа состоит в том, чтобы уменьшить погрешности вычислений стандартных форматов с плавающей точкой.
Эмуляция повышенной точности
Увеличим объем памяти, выделяемый под мантиссу, и показатель степени и переопределим основные операции арифметики: +, -, *, /. Это можно сделать следующим образом. Создадим структуру, которая будет содержать 32 бита под мантиссу, 32 бита под показатель степени и 1 бит под знак. По точности наш формат будет будет превосходить формат float на две десятичных значащих цифры. Для дальнейшего увеличения точности и определения мантиссы можно использовать массив чисел формата unsigned int.
unsigned int mantissa; unsigned int exp; bool sign;
myFloat operator+ ( myFloat &); >;
Далее определим операцию суммирования. Чтобы сложить два числа, сначала выравниваем показатели степеней. Для этого сдвинем мантиссу числа с меньшим показателем степени вправо на количество бит, равное разнице между показателями степени, после чего складываем мантиссы. При сложении мантисс может появится единица в старшем бите, поэтому надо проверить результат операции. Если в результате сложения получилось число меньше какого-либо слагаемого, то есть произошло переполнение, то необходимо сдвинуть мантиссу результата на один бит вправо и записать единицу в нулевой бит. Далее приведен код программы на C++, реализующий операцию сложения.
myFloat myFloat :: operator+ ( myFloat & ff2 )
if ( exp >= ff2 . exp )
unsigned int diff = ff2.mantissa >> ( exp - ff2.exp ); res.exp = exp; res.sign = sign;
res.mantissa = mantissa + diff;
res.mantissa = res.mantissa >> 1; res.mantissa = res.mantissa | 0x80000000 ;
unsigned int diff = mantissa >> ( ff2.exp - exp );
res.mantissa = ff2.mantissa + diff;
res.mantissa = res.mantissa >> 1; res.mantissa = res.mantissa | 0x80000000;
Теперь определим операцию умножения. При умножении двух чисел нашего формата необходимо перемножить мантиссы, сложить показатели степени и определить знак результата. Перемножение мантисс делается следующим образом. Если в мантиссе второго сомножителя на i-м месте стоит единица, то необходимо сдвинуть мантиссу первого множителя на i бит вправо и прибавить к результату. Знак результата операции будет положительным, если знаки сомножителей совпадают, и отрицательным, - если не совпадают.
myFloat myFloat :: operator* ( myFloat & ff2 )
uint tmp = mantissa;
for ( uint i = 0x4 0000000; i != 0; i >> 1)
if (( ff2.mantissa & i) == i)
uint oldmantissa = res.mantissa; res.mantissa = res.mantissa + tmp;
res.mantissa = res.mantissa >> 1; res.matice = res.mantissa | 0x80000000; res.exp = res.exp + 1;
res.exp = res.exp + exp + ff2.exp; if ( sign == ff2.sign ) res.sign = 0; else
Подобным образом можно определить операции вычитания и деления. При применении рассматриваемого метода к решению исходной задачи мы получили, что время работы алгоритма с применением графического процессора с двойной точностью сопоставимо со временем работы центрального процессора с типом данных float. Тем самым, использование тира double с применением графического процессора перестает быть затратным по времени.
Отсутствие большего выигрыша по скорости можно объяснить тем, что при вычислениях по данному методу относительно редко встречаются операции, которые значительно быстрее выполняются на GPU (например, перемножение элементов массива), а выигрыш от использования графического процессора при поэлементном сложении двух массивов незначителен.
Снижение погрешностей в вычислениях с плавающей точкой одинарной и двойной точности
Смысл этого метода состоит в том, чтобы складывать или вычитать числа, близкие по показателям степени. Рассмотрим пример. Пусть имеется число f формата float, равное 100.000.000. Будем прибавлять к нему миллион раз единицу. В результате получим тоже число, равное 100.000.000, что неверно, поскольку формат float вмещает только 7-8 значащих цифр. Рассмотрим подробнее операцию сложения. Для этого определим наш формат как структуру, состоящую из вектора чисел формата float.
newFloat operator+ ( newFloat & ); >;
Пусть есть два экземпляра структуры newFloat: ff1, ff2. Чтобы сложить их, будем переписывать числа из вектора ff2::ff в ff1::ff следующим образом: берем число из ff2::ff и ищем в векторе ff1::ff такое число, чтобы модуль разности показателей степени этих чисел был меньше определенного числа. Выбор этого числа зависит от формата чисел в векторе. Если в векторе ff1::fff, такое число нашлось, то мы их суммируем, если нет, то дописываем число из ff2::ff в конец ff1::ff. После того, как все необходимые сложения в программе выполнятся, мы получим вектор чисел. Далее, чтобы получить ответ, необходимо упорядочить этот вектор по возрастанию и просуммировать все его элементы начиная с нулевого. В результате всех этих операций мы значительно уменьшим количество сложений чисел с сильно различающимися показателями степени.
Далее приведем исходный код основных операций для операции сложения. Суммирование двух элементов формата myFloat:
newFloat & newFloat::operator+ ( newFloat & ff2 )
uint* bb = ( uint*)( void*)(& ff2 [i]); uint exp2 = (bb > 16;
uint* aa = ( uint*)( void*)(& this [j]); uint exp1 = (aa > 16;
Сортировка вектора и суммирование вектора чисел:
( uint i ( uint j = i; j < ff.size ff[i] >ff[j])
i Не можете найти то, что вам нужно? Попробуйте сервис подбора литературы.
float tmp; tmp = ff[i]; ff[i] = ff[j];
float answ = 0; for ( uint i = 0; answ = answ + ff[i] return answ;
Вновь рассмотрим предыдущий пример. В результате первого сложения чисел 100.000.000 и 1, мы получим вектор . При следующем сложении вектор будет иметь вид . В конечном итоге, нам придется складывать числа, близкие по показателю степени, что даст верный результат.
Эксперименты по использованию данного метода при решении описанной в начале статьи задачи показали, что с применением графического процессора скорость выполнения указанного алгоритма увеличивается в два раза. Этот показатель ниже заявленного производителями графических карт. Объяснение подобной ситуации заключается в том, что данный метод использует сортировку и прочие операции с данными, которые могут вызывать множественные коллизии обращения к памяти.
Рассмотренные способы реализации вычислений повышенной точности требуют много времени на выполнение расчетов. Но при больших объемах данных и высокой сложности вычислений данные способы можно реализовать на архитектуре графических процессоров, что позволит существенно сократить время выполнения вычислений. Выигрыш во времени вычислений достигается благодаря тому, что графические процессоры содержат сотни потоковых ядер, что позволяет запустить вычислительный алгоритм, если его можно распараллелить, в большом количестве потоков выполнения. Для сравнения, в настоящий момент максимальное число ядер для центрального процессора равняется 12 (AMD Opteron 6174), для графических процессоров это число составляет 1600 (ATI Radeon HD 5870).
Представленные методы были применены к вычислительной задаче поиска решения уравнения. Результаты показали, что использование графических процессоров в сочетании с правильной организацией данных и действий над ними дают неплохой результат. Пред-
ложенный подход к решению поставленной задачи позволил увеличить размер разрядной сетки, не уменьшая скорости, а также понизить погрешность в вычислениях с плавающей точкой.
1. Литвинов, Г.Л. Приближенная рациональная арифметика с контролируемыми ошибками округления / Г.Л. Литвинов, А.Я. Радионов, А.В. Чуркин. - М.: Вычислительные технологии, 2001. Т. 6. С. 87-94.
Дата поступления в редакцию 11.10.2011
R.M. Dmitrienko, A.A. Emelyanov, S.A. Zolotov, V.U. Klimashov, S.A. Savikhin, A.B. Terentev
THE PROBLEM OF THE COMPUTING PRECISION OF THE PHASE VARIATION METHOD
This paper describes methods of precision improvement and computing error reduction as applied to the problem of phase variation-based equation roots solving. Estimations for the performance of GPU-based implementations of this method are given in the paper as well.
Key words: numerical computing, variation, logarithmic residue, mantissa, precision.