Stas633 0 28 декабря, 2008 Опубликовано 28 декабря, 2008 · Жалоба Известно, что работа (выполнение арифметических операций) с целыми числами проще чем с дробными. Многие MC имеют в своем составе аппаратные умножители целых цисел. ("старшие" MC - DSP, ARM9 и др., имеющие мат.сопроцессоры, не рассматриваем). Изначально, все внутренние входные, "аппаратные" данные в MC (АЦП, таймер/счетчик) являются целыми. Но как только необходимо произвести операцию деления, то рассматриваемые числа "перестают" быть целыми, появляется целая и дробная, иногда равная 0, части. Для того чтобы не "потерять" остаток есть, на мой взгляд, два пути: 1. Увеличить разрядность чисел до необходимой точности (перед делением ужножить делимое и делитель, например, на 1000, тогда частное будет... (не продолжаю - очевидно) ); 2. Работать не с целыми (int, long), а с дробными (float) числами. Второй вариант мне кажеться предпочтительнее - не нужно ни "запоминать" (в уме и программе) точность, ни производить дополнительных преобразований перед вычислениями. Однако, какова степень оверхеда кода и времени вычислений, затрачиваемого на алгеброические операции с числами с плавающей точкой, в сравнении с п.1? ... P.S. Естественно, что вопрос не про собственно операцию деления, а про то, что перейдя к float, "придется" работать с float во всех остальных арифмет.действиях, использовать float в качестве аргументов и возвращаемых значений функций и т.д. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 28 декабря, 2008 Опубликовано 28 декабря, 2008 · Жалоба Все зависит от того, что вы собираетесь с вычисленными значениями делать. Да и что за задача (чисто вычислительная или управление чем-то). Плавающая точка содержит кучу подводных камней (помимо скорости вычисления). В 70-х годах было издано довольно много книг, посвященных вопросам точности вычислений. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
arttab 0 28 декабря, 2008 Опубликовано 28 декабря, 2008 · Жалоба можно делить на 2 в степени n. можно умножить на 10, 100... потом делить и получите требуемую точность. а можно и не делить а работать с не поделенными значениями. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Stas633 0 28 декабря, 2008 Опубликовано 28 декабря, 2008 · Жалоба Все зависит от того, что вы собираетесь с вычисленными значениями делать. Да и что за задача (чисто вычислительная или управление чем-то). Не хотелось бы "углубляться", но... например. Один вариант - нужно расчитать значение и вывести его на индикатор. Выводить в формате плавающей точки ("1.234E-2"), согласитесь, не привычно для "глаза". Нужно точку "фиксировать" (0,01234). Другой вариант - нужно на расчитанное значение позиционировать, например, инструмент станка (руку робота и т.д.). И опять придется переводить float значение к единицам позиционирования (к ЦЕЛОМУ их числу). (А если дискретность перемещения не имеет 10-ное основание, то преобразование еще "длиннее"). Т.е. на лицо необходимость "обратного" преобразования float -> long. /НO!, вместе с тем, функции, написанные с использованием float, проще для "понимания", переносимее, универсальнее, если хотите./ Что может быть разным в этих вариантах? (с точки зрения работы с float) Плавающая точка содержит кучу подводных камней (помимо скорости вычисления). В 70-х годах было издано довольно много книг, посвященных вопросам точности вычислений. Каких именно? И еще одно уточнение... Вопрос достижения заданной точности не рассматривается. Хочется сравнить LONG v/s FLOAT /оверхед & скорость/ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 28 декабря, 2008 Опубликовано 28 декабря, 2008 · Жалоба Хочется сравнить LONG v/s FLOAT /оверхед & скорость/ Кесарю-кесарево. Математика (синусы, косинусы) вся на float? Гут - будем в плавучке. А управляющие алгоритмы редко выходят на плавучку - больше на long. Вот такой водораздел... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Stas633 0 28 декабря, 2008 Опубликовано 28 декабря, 2008 · Жалоба можно делить на 2 в степени n. Согласен. С точки зрения кода это, безусловно, и быстрее, и короче (чем умножение/деление на 10^n) - умножение и деление на 2 это, как известно, сдвиг, который длится 1 такт (с учетом разрядности МС конечно), но, тем не менее, это лишние, избыточные действия о которых НЕОБХОДИМО помнить при написании программы. А как быть если в различные моменты работы программы нужна разная точность? Передавать функции точность вычислений в качестве аргумента? Или писать несколько функций? Кесарю-кесарево. Математика (синусы, косинусы) вся на float? Гут - будем в плавучке. А управляющие алгоритмы редко выходят на плавучку - больше на long. Вот такой водораздел... Опять в "крайности"(сложности). Конечно, "тригономертию" без float ни как, но где та грань (водораздел, ватерлиния) когда "уже нужно"? Возведение в степень, деление..? ... Хорошо.. тогда так: допустим, необходимо вычислять такую фунцкию y=(x^2 + k) / z Вроде "МАТЕМАТИКИ" нет, но если не использовать float, то сразу возникает, как минимум, один вопрос: с какой точностью нужно производить вычисления? А если достаточная точность неизвестна перед началом программирования, да и вообще, может быть различной? ...... ...... Если попытаться ответить на вопрос топика, то правильно ли мнение, что: В случае, когда необходимая точность вычислений известна и не меняется, и математические формулы ограничены четырмя основными арифметическими действиями (+, -, *, /), то целесообразно применение long переменных, с соответствующими преобразованиями. В остальных случаях лучше, правильнее применять float. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 28 декабря, 2008 Опубликовано 28 декабря, 2008 · Жалоба Опять в "крайности"(сложности) Пример, недавно обсуждаемый: накапливающее суммирование. Если точность вмещается в мантиссу - пожалста, плавучка применима. Если нет - происходит накопление ошибки округления. А сие очень часто возможно, если вспомнить про 24-разрядные АЦП. Опять про водораздел: например, некая моделька на борту контроллера, считается что-то методом Ньютона-Раффсона. Плавучка? Конечно! Но вот моделька соприкасается с реальностью - 10-разрядные АЦП/ЦАП, таймера с тиком 100мкс... Что мы делаем? Только dst = SCALE * round(). В случае, когда необходимая точность вычислений известна и не меняется Я бы оставил так Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 28 декабря, 2008 Опубликовано 28 декабря, 2008 · Жалоба умножение и деление на 2 это, как известно, сдвиг, который длится 1 такт (с учетом разрядности МС конечно), но, тем не менее, это лишние, избыточные действия о которых НЕОБХОДИМО помнить при написании программы.Можно возложить это на компилятор - прямая дорога в плюсы, заводите класс "число с фиксированной точкой", пишите для него преобразования и арифметику, дальше работаете как с обычными переменными.А как быть если в различные моменты работы программы нужна разная точность?Ну, тут float не сильно поможет. Его точность определяется разрядностью мантиссы и для 4-байтового float (23 бита мантисса, реально 24 бита за счет нормализации) составляет log10(2^24) ~ чуть больше 7 десятичных знаков. Диапазон чисел с плавающей точкой, да, большой, и определяется разрядностью экспоненты. Поэтому если вы попытаетесь сложить 1 и 1e-8, вы получите ту же 1, чудес нет. Используя те же 32 бита в формате фиксированной точки можно получить log10(2^32) 9.6 десятичных знаков, но в существено меньшем диапазоне. Скорость вычислений с плавающей точкой будет ниже (не рассматриваем специально заточенный (со)процессор), потому что перед каждым действием операнды приводятся к одной экспоненте, а после действия результат нормализуется (мантисса приводится к двоичному виду 1.ххххх). Конечно, "тригономертию" без float никак,Почему? Тригонометрия реализуется и в фиксированной точке.но где та грань (водораздел, ватерлиния) когда "уже нужно"?Хороший вопрос, тянет на диссертацию ;) Наверное так: Если значения имеют большой диапазон, если точность и скорость float устраивает, то приносим размер кода и скорость в жертву универсальности и простоте написания - использует float. Если точность или скорость не устраивают - используем фиксированную точку. Насчет размера нужно пробовать - не факт, что сколь-нибудь полная реализация арифметики с фиксированной точкой получится компактнее. P.S. бывают случаи, когда не подходит ни тот, ни другой формат. И тогда арифметика реализуется прямо в десятичном виде, с BCD представлением чисел и изменяемой длиной числа. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 28 декабря, 2008 Опубликовано 28 декабря, 2008 · Жалоба Насчет размера нужно пробовать - не факт, что сколь-нибудь полная реализация арифметики с фиксированной точкой получится компактнее. При аддитивных операциях - фиксированная быстрее из-за того, что не надо выравнивать порядки, при умножении - проигрыш так себе, не пугает, компромиссы возможны. А деление - это грустно :( , зато применим компактный алгоритм деления чисел произвольной длины. ЗЫ я конечно же про камни без FPU :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Stas633 0 28 декабря, 2008 Опубликовано 28 декабря, 2008 · Жалоба Почему? Тригонометрия реализуется и в фиксированной точке. Конечно, как и вычисление иттераций при реализации метода Ньютона.. :) Но в этом случае задача видоизменяется в задачу написания своей библиотеки. Стандартные библ. работают с плавающей точкой (возможно не все). Можно возложить это на компилятор - прямая дорога в плюсы, заводите класс "число с фиксированной точкой", пишите для него преобразования и арифметику, дальше работаете как с обычными переменными. Спасибо! :a14: Лежало на поверхности, но "глаза не видят" и "мозг не думает". P.S. бывают случаи, когда не подходит ни тот, ни другой формат. И тогда арифметика реализуется прямо в десятичном виде, с BCD представлением чисел и изменяемой длиной числа. Спасибо за идею! :) .... Попытаюсь "переписать" ответы: Главное - преобразования присутствуют везде. long - приведение к заданной точности, float - приведение к одной экспоненте и нормализация результата. При этом работа с целыми быстрее. "Итого:" Если применение "плавающей точки" не продиктовано использованием готового кода (библ.) То для написания более "быстрого" кода, необходимо использовать "фикс.точку". А для приведения целых чисел к заданной точности использовать умножение/деление не на 10^n, а 2^n. Если же скорость работы про-ца достаточна (или есть встроенный FPU), и точность вычислений обеспечивается разрядностью мантиссы, то - "плавающая точка". .... Спасибо. С Наступающим! Удачи! :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lelikk 0 4 января, 2009 Опубликовано 4 января, 2009 · Жалоба С float-ами следует быть вообще очень аккуратным, и переходить к ним только в крайнем случае. Ведь на процах без аппаратного FPU все операции реализуются программно, то есть дико тормозно. Специально смотрел километровый ассемблерный листинг для __fdiv, который используется компилером. Более того, по-мимо тормознутости есть большая опасность наткнуться на странные глюки - приведу конкретный пример. На проце TMS320F2806 FPU нет, однако разбираться с поставляемой ti библиотекой для фиксированной точки времени не было, поэтому все забили через float. Так как расчетов было немного, то тормоза не влияли, но обнаружилось, что библиотечный cos - функция расходящаяся... :crying: В большой запарке пришлось написать свой разложением в ряд, потому что для лучшего времени не было... Теперь зарекся использователь по крайней мере на tms софтварные float. Так что даже использование стандартной либы может натолкнуться на глючную реализацию у компилятора.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться