Главная
Главная страница, новости
Компьютерные тренажеры
· Обзорная статья
· Конструктор
· Тренажеры (продукты)
· Теплосети
· Как заказать
SCADA Другие проекты
· Сад Слов
· Almik
Публикации
· Основные публикации
· Блог ЖЖ
· Путешествия
· Живопись
. Лирика
Об авторе Rambler's Top100

Донской А.Н.
10 августа 2007

ТРИЗ В ПРОГРАММИРОВАНИИ

Вот по случаю вспомнил про ТРИЗ (Теорию Решения Изобретательских Задач) и решил написать эти короткие заметки.

Возникла тут одна программистская задача, вкратце выглядит так. Есть 16-разрядное микропроцессорное устройство без плавающей арифметики. Есть необходимость масштабирования сигналов. То есть измеренное (в дискретах) 16-разрядное целое надо умножить на масштабный коэффициент (конечно, вещественный в общем случае), чтобы получить значение в нужном диапазоне и в нужных величинах (скажем, в амперах).

Старшее поколение инженеров, начинавшее с аналоговых вычислительных машин (АВМ), хорошо знает задачу масштабирования (приведения в нужный диапазон) и все ее подводные камни. Для тех, кто с этим не сталкивался, поясню, что вся задача как таковая возникает исключительно из-за ограниченности диапазона представления величин. При использовании вещественной (плавающей) арифметики проблема снимается (ну или отодвигается в достаточно необозримые дали, поскольку допустимый диапазон составляет несколько десятков порядков, например, от 1e-36 до 1e36). Однако в 16 двоичных разрядах имеем диапазон всего-то от 0 до 65535, что маловато. Причем, если в АВМ переполнение приводит только к ограничению сигнала, то 16-разрядная арифметика будет давать совершенно непредсказуемые (на человеческий взгляд) результаты. Псувдослучайные, можно сказать. Сложно отлаживать такие ситуации, если заранее не учесть все возможные диапазоны исходных сигналов, калибровочных параметров и промежуточных вычислений.

Подходим к решению задачи грамотно и решаем типовым образом - вещественный по сути масштабный коэффициент раскладывается на пару 16-разрядных целых - множитель m и делитель d. Тогда операция масштабирования в целочисленной арифметике выглядит как умножение 16-разрядных сигнала и множителя m с получением 32-разрядного результата и последующим его делением на 16-разрядный делитель d. Результат опять 16-разрядный.

Как рассчитать коэффициенты m и d (ведь k=1.55555 можно грубо представить как m=16 и d=10, а можно и как m=15556 и d=10000, или еще точнее как m=31111 и d=20000)? Очевидно, что при наибольших возможных значениях m и d обеспечивается наибольшая точность.

В том же случае, когда искомый масштабный коэффициент представляет собой функцию от ряда параметров настройки, вычисление итоговых пар m и d становится особенно веселым и совсем не тривиальным. Например, если m=m1*m2, то при m1=1000 и m2=10000 мы не можем вычислить (и сохранить в 16 разрядах) итоговый множитель m из-за переполнения. Тогда приходится "сокращать нули" путем деления числителя и знаменателя на определенное число (например, m=m1*m2/1000; d=d/1000). При этом может произойти очередная потеря точности (например, d=1234 превратится в d=1).

Наконец, следует упомянуть о дополнительных условиях, которые, хотя и относятся непосредственно к теме (явно выражаются в формулах), но постоянно забываются программистом, перегруженным текучкой (в нашем случае коэффициент k следовало еще всегда умножать на 1000, поскольку выходной отмасштабированный результат должен отображаться на дисплее устройства в формате с фиксированной точкой - 3 разряда после точки).

Зачем я так подробно описываю задачу и проблемы? Во-первых, чтобы показать тем, кому будет интересно, как решаются типовые задачи масштабирования в целочисленной арифметике. А во-вторых, и это главное, показать, как за объемистым нагромождением условий и формул сама задача перестает быть прозрачной; а обыкновенное стремление ленивого программиста, каковыми является большинство из нас, решить ее наскоком, держа все условия в голове, заканчивается позорным блужданием в трех соснах в течение длительного непродуктивно потраченного времени.

Итак, задача давно и успешно решена, для каждой группы сигналов рассчитываются пары коэффициентов, все довольны и все забыли процесс решения задачи давно и прочно.

И в один прекрасный момент, вдруг, возникает проблема. Требуется обслужить еще одну группу сигналов. Пожав плечами, вспоминаем решение задачи и в лоб пишем еще одну формулу для соответствующих коэффициентов m и d, нарываясь с ходу на переполнение в числителе. Еще раз пожав плечами и лукаво не мудрствуя, делим m и одновременно d на 1000 и отдаем на испытания.

Результат обескураживает - на дисплее отображается полный бред. Проверяем, откуда руки у испытателей растут и как они задали исходные параметры. Убеждаемся, что задали неправильно. Задаем правильно и снова получаем бред. Чешем репу в районе затылка и находим ошибку в формуле вычисления m. Теперь все правильно, но отображается тот же бред. При отладке обнаруживается, что делитель d был равен 500, но после того, как его вместе с множителем m поделили на 1000, чтобы избежать переполнения, вместо одной проблемы имеем другую - в знаменателе получился ноль!

Ладно, долго возимся, но путем дополнительных сокращений обеспечиваем что-то путевое и в нужном диапазоне. Отдаем на испытания. Испытатели радуются, но потом обиженно отмечают, что отображаемое значение в 1000 раз меньше, чем должно быть. Головы у всех чугунные, но соображаем достаточно быстро, что забыли m на 1000 умножить (см.выше про отображение с фиксированной точкой). Но позвольте, однако ж, у нас уже в предельном случае m=60000, в то время как d=1! Множитель m на 1000 умножать некуда - переполнение, а делитель на 1000 делить тоже некуда!

Вытираем пот со лба, собираем маленькое производственное совещание (прибор должен быть отгружен на прошлой неделе!), обсуждаем еще раз всю проблему со всех сторон и приходим к выводу, что задача невыполнима. Предлагается ограничить диапазон исходных данных для вычисления коэффициентов, но это нельзя. Останавливаемся на том, что вообще не будем показывать эти сигналы в абсолютных величинах, а только в относительных - все равно у конкурентов только относительные используются.

Тут один товарищ (назовем его "представителем заказчика", хотя это не то, что подразумевалось в советское время; просто подчеркнем, что к процессу программирования устройства в этой его части он имеет весьма косвенное отношение) говорит - а у нас там что? Амперы? И в 1000 раз меньше показывает? Ну так давайте напишем, что это КИЛОамперы, и все будет как надо!

Я обрадовался, он обрадовался, а начальник почесал репу и сказал, что не верит в такие простые решения... Не бывает так, чтобы приходили с глобально фатальной проблемой, а уходили с тем, что и делать ничего не надо вовсе! Тут я сразу про ТРИЗ и вспомнил. ИКР это называется, то бишь Идеальный Конечный Результат. Совершенно классический пример - и делать ничего не надо, и проблема решена!

Проблема: показывает в 1000 раз меньше, чем надо.
Противоречие: можно изменять масштабный коэффициент, но нельзя его изменить из-за переполнения.
ИКР: масштабный коэффициент не меняется, но показания становятся правильными.
Решение: меняем масштаб отображаемых величин за счет перехода к другим единицам измерения.

Спрашивается, сколько бы мы все вместе времени сэкономили, если бы оторвались от текучки и не зациклились, спотыкаясь на хорошо проторенной дорожке, а сразу мыслили по-тризовски от технического противоречия к ИКР?

ССЫЛКИ ПО ТЕМЕ:

www.altshuller.ru - Официальный сайт Фонда Г.С.Альтшуллера (автора ТРИЗ-РТВ-ТРТЛ)
www.trizland.ru - TrizLand - сайт о ТРИЗ - Все, что вы хотели знать о теории решения изобретательских задач
www.triz-summit.ru - ТРИЗ САММИТ - Официальный сайт Саммита Разработчиков ТРИЗ.
www.matriz.ru - Официальный сайт Международной ассоциации ТРИЗ (Теории решения изобретательских задач)
www.metodolog.ru - сайт посвящен изобретательским задачам и методам их решения
www.temm.ru - Теория эволюции материи и моделей - ТЭММ
groups.google.com/group/fido7.ru.triz/ - Конференция fido7.ru.triz

Home Page

http://simulators.narod.ru
Post: 428000, г.Чебоксары, а/я 121,
Донской Алексей Николаевич
Адрес изображен картинкой для защиты от спам-роботов
Rambler's Top100
Сайт управляется системой uCoz