06-floating1 (1238881)
Текст из файла
ПЛАВАЮЩИЕ ЧИСЛАПредставления чисел с плавающей точкой и операции над ними.Точность вычислений. Поиск корней уравненийК. Владимиров, Intel, 2019mail-to: konstantin.vladimirov@gmail.comНемного о работе компьютера•Память позволяет хранить ограниченное число бит•Каждая операция в компьютере производится над ограниченным числом бит00000000 <_add>:int add(int x, int y) {return x + y;•0: 8b 44 24 08moveax, DWORD PTR [esp+0x8]4: 03 44 24 04addeax, DWORD PTR [esp+0x4]Естественный способ трактовать ограниченное число бит: как натуральноечислоОт натуральных к целым•Естественный способ думать об ограниченных целых числах: как о сдвинутыхвправо натуральных0-127•255128Но поскольку диапазон всё равно ограничен... Например, сколько будет вбеззнаковых числах 0u – 1u?От натуральных к целым•Естественный способ думать об ограниченных целых числах: как о сдвинутыхвправо натуральных129-127•255 00255128 -127-1Целые числа обычно закодированы как верхний диапазон натуральных вобратном порядке (поэтому у них всегда выставлен верхний "знаковый" бит)Обсуждение•Как закодировать вещественные числа?•Первая идея кодировка с фиксированной точностью2−32•Эта идея иногда находит применения, но в целом она очень плоха:•••0232маленькие диапазоны чисел (64-битное плавающее число не больше чем 232 )низкая точность: размер шага не больше, чем 2−32 это слишком крупный шаг длямногих практических примененийМожно генерировать вещественное число бит за битомПлавающая точность•Для научных вычислений принято приближать вещественные числарациональными, используя идею плавающей точки•Например мы договариваемся, что у нас есть 8 значащих разрядов.
Тогда сплавающей точкой возможны числа: 1024561, 10245.61, 10.24561,1.024561•Это было осознано довольно рано и после ряда попыток разной успешности,стандартизовано в 1985 году (см. )•Сейчас это фактический стандарт, от которого крайне редко отступаютПредставление с плавающей точкой•Представление ±1.
∗ 2−127 при этом (exp > 0) && (exp < 255)s exponentfractional part of mantissa0 0 1 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 031230•Например на рисунке представлено какое-то число•exp – 127 = 124 – 127 = -3•mantissa = +1.01b = 1 +•Вместе: 1.25 * 2−3 = 0.15625f14= 1.25f*значения 0 и 255 зарезервированы на особые случаиПредставление с плавающей точкой•Представление ±1.
∗ 2−127 при этом (exp > 0) && (exp < 255)s exponentfractional part of mantissa1 1 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 031230•Например на рисунке представлено какое-то число•exp – 127 = 129 – 127 = 2•mantissa = -1.011b = − 1 + +•Вместе: -1.375f * 22 = -5.5f1418= -1.375fОбсуждение•У такого формата есть один недостаток: нельзя представить 0•Найдите самое близкое к нулю числоs exponentfractional part of mantissa0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 031230Обсуждение•У такого формата есть один недостаток: нельзя представить 0•Найдите самое близкое к нулю числоs exponentfractional part of mantissa0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 031230•Имеем 2−126 это довольно большое число и это точно не нольДенормализованные числа•Cпециальное значение exp = 0 соответствует денормализованным числам•Нормализованные: ±1.
∗ 2−127 при этом exp > 0•Денормализованные: ±0. ∗ 2−126 при этом exp == 0s exponentfractional part of mantissa0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 031230•Благодаря этому число, состоящее изо всех нулей это ноль, что интуитивноправильно.•Контринтуитивно здесь то, что возможен -0.0, отличающийся от +0.0 припобитовом сравненииБесконечности•Экспонента, состоящая изо всех единиц (e = 255) отображает ±∞s exponentfractional part of mantissa0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 031230s exponentfractional part of mantissa1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 031230Концепция not-a-number•Число, представляющее собой неопределённость (например результатделения нуля на ноль) называется NaNs exponentfractional part of mantissa0 1 1 1 1 1 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 031230•NaN это exp=255 и любая ненулевая fraction•Первый бит fraction отличает qNaN от sNaN, но это не часть семантики языка•Сравнение чего угодно с NaN даёт false, в т.
ч. NaN не равен сам себе (ипоэтому он не число)Problem EX – работа с битами чисел•Вам дано число с плавающей точкой типа float (мантисса 23 нижних бита)•Вы должны получить из него другое число с плавающей точкой,инвертировав все нечётные биты мантиссы (нулевой бит считается чётным) инапечатать с точностью до пятого знака после запятойУпражнения•Запишите в формате floating-point число 1.0f•Число 0.1f не представимо в формате floating-point точно. Постройтелучшее возможное приближение.
Насколько оно хорошо?1• Число тоже нельзя точно представить. Какое будет лучшее приближение3этого числа?•Охарактеризуйте все числа, которые можно представить точно. Напримерчто вы скажете о числе 0.0361328125f?•Какое расстояние между самым большим по модулю нормализованнымчислом и следующим за ним?Быстрый приближённый логарифм•В следующей таблице приведены значения чисел и их логарифмов пооснованию 2ЧислоПредставлениеПредставлениеминус 0x3f800000Логарифм1.0f0x3f8000000x000000000.0f2.0f0x400000000x008000001.0f4.0f0x408000000x010000002.0f•Из этого следует интересная формула•log(x) ≃ ([x as bits] - 0x3f800000) / 0x00800000Обсуждение•Разница между приведением и трактовкой как биты очень великаfloat x = 1.0f;unsigned i = (unsigned) x; // i == 1•Это приведение (cast)float x2 = 1.0f;unsigned i2 = *(unsigned *) &x2; // i == 0x3f800000•Это трактовка как биты (reinterpretation)Strict aliasing•Правилами языка запрещён алиасинг двумя разными типами на один объектfloat x2 = 1.0f;unsigned *pi2 = (unsigned *) &x2; // aliasing•Здесь одна ячейка в памяти имеет два имени для доступа и это очень плохо•Можно выкрутится чем-то вроде:unsigned as_uint(float f) { return *(unsigned *) &f; }unsigned i2 = as_uint(x2);•Здесь у нас не будет strict aliasing violation, т.
к. нас интересует значениеБыстрые приближения•Можно реализовать быстрый логарифм на базе формулыlog(x) ≃ (float) (as_uint(x) - 0x3f800000) / (float) 0x00800000•Давайте потратим некоторое время на анализ того как это вообще можетработатьБыстрые приближения•Можно реализовать быстрый логарифм на базе формулыlog(x) ≃ (float) ([x as bits] - 0x3f800000) / (float) 0x00800000•Реализуйте также быстрое возведение двойки в данную степень2 ≃ [((unsigned) (x * (float)0x00800000) + 0x3f800000) as float]•Подобная же магия возможна и для квадратного корня ≃ [(([x as bits] >> 1) + (0x3f800000 >> 1)) as float]•Сравните с функциями логарифма, возведения в степень и извлечения корнястандартной библиотеки.
Имеет ли на вашей системе эта магия реальный смысл?Концепция ulp•"Unit in the last place" это расстояние между двумя последовательнымичислами с плавающей точкой•Например посчитаем ulp(1.0f)float d0, d1;d0 = 1.0f;d1 = nextafterf(d0, d0 + 1.0f);printf("%.8f", d1 - d0); // на экране 0.00000012•Все вычисления над парой чисел z = x (op) y должны быть округлены впределах 0.5*ulp(z)Важность округления•Результат, полученный после арифметической операции внутри ulp, должен бытьокруглён к ближайшему представимому значению•Округлять можно вверх, вниз, к нулю и к ближайшему•Для выставления метода округления используется функция fesetroundfloat a = 1.0, b = 3.0;fesetround(FE_UPWARD);fesetround(FE_DOWNWARD);fesetround(FE_TONEAREST);fesetround(FE_TOWARDZERO);assert(as_uint(aassert(as_uint(aassert(as_uint(aassert(as_uint(a////b)b)b)b)========0x3eaaaaab);0x3eaaaaaa);0x3eaaaaab);0x3eaaaaaa);Problem RP – верхняя и нижняя границы•Пользователь вводит числитель и знаменатель дроби•На выходе верхняя и нижняя аппроксимации при представлении в форматеfloat как два шестнадцатиричных числа: экспонента и дробная частьмантиссы•Если возможно точное представление, они должны совпадатьinput:1 3output:0x7d 0x2aaaaa 0x7d 0x2aaaabсм.
также https://www.h-schmidt.net/FloatConverter/IEEE754.htmlРазная точность•В языке C поддержаны три уровня точности: float, double, long double•float это обычные 32-битные плавающие числа•double это 64-битные плавающие числа•long double часто совпадает с double, но иногда (в таких компиляторах какgcc) оно реализуется через extended-precision 80-битные числаТипbits in exponentfloat8237-8double115215-16long double*166420-21bits in fractionsignificant decimal digits*не всегда, см. текст слайдаУпражнение•Первые знаки числа π в двоичной записи11.001001000011111101101010100010001000010110100011000010001101001100010011000110011000101000101110000000110111000001110011010001001010010000001•Запишите наиболее близкое к π представление с одинарной и с двойнойточностьюОсновные правила•Работа с плавающими числами имеет свою специфику.
Характеристики
Тип файла PDF
PDF-формат наиболее широко используется для просмотра любого типа файлов на любом устройстве. В него можно сохранить документ, таблицы, презентацию, текст, чертежи, вычисления, графики и всё остальное, что можно показать на экране любого устройства. Именно его лучше всего использовать для печати.
Например, если Вам нужно распечатать чертёж из автокада, Вы сохраните чертёж на флешку, но будет ли автокад в пункте печати? А если будет, то нужная версия с нужными библиотеками? Именно для этого и нужен формат PDF - в нём точно будет показано верно вне зависимости от того, в какой программе создали PDF-файл и есть ли нужная программа для его просмотра.