2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу Пред.  1, 2, 3, 4, 5, 6 ... 10  След.
 
 
Сообщение18.01.2006, 23:23 
Заслуженный участник
Аватара пользователя


17/10/05
3709
:evil:
Уже не помню. Давно дело было, в эпоху gopher'а...

 Профиль  
                  
 
 
Сообщение21.01.2006, 19:05 
Заслуженный участник
Аватара пользователя


12/10/05
478
Казань
bekas писал(а):
Хотелось бы услышать от практикующих программистов о самых
запомнившихся (казусных) ошибках программирования из их
практики. А таковых, наверняка, было немало...


Продолжим? Я бы хотел заодно еще услышать и об ошибках, обнаружение которых доставило максимум хлопот. Иначе говоря, от том, чего делать нельзя. :) (Но то, что этого делать нельзя, на первый взгляд, неочевидно)

 Профиль  
                  
 
 ошибок вообще делать нельзя, любых.
Сообщение21.01.2006, 20:17 


02/08/05
55
ну например, нельзя пользоваться неустойчивыми схемами, это не всегда сразу видно.
нельзя путать неустойчивую схему и некорректно поставленную задачу.
и лучше всего если схемы неявные. для пятиточечных аппроксимаций есть метод пятиточечной прогонки, это гораздо точнее обычной аппроксимации.

а что касается собственно программирования - смотря на каком языке работаете. если это СИ (не пытайтесь выучить этот язык первым) то индексы должны быть в пределах выделенной динамической памяти. если выйти при счете то компилятор эту ошибку не заметит и программа не обязательно упадет но счета естественно не будет.


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

 Профиль  
                  
 
 Re: ошибок вообще делать нельзя, любых.
Сообщение22.01.2006, 14:45 
Заслуженный участник
Аватара пользователя


12/10/05
478
Казань
вв писал(а):
вот у меня раз было, это строго говоря не ошибка но запомнилось. решается задача Коши для дифура в частных производных, сначала по пятиточечной аппроксимации а потом по трехточечной, для скорости. так оказалось что перед сменой аппроксимации нужно освободить всю память и определить ее снова. а если этого не сделать то компилятор чтО то чудит и делает так что программа считает на четверть медленнее.


У меня тоже было нечто... :) Тоже не ошибка, и тоже запомнилось, хотя совсем из иной области, нежели Ваш пример. Мой излюбленный способ загружать в память текстовые таблицы из файлов следующий:
1) Загружаем весь файл в память (нечто вроде
char *data = (char *)malloc(filelength(fileno(f_id))+1);
fread(data, 1, filelength(fileno(f_id)), f_id));
2) Потом, для разбора используем функцию strtod(char *ptr, сhar **endptr):
x[i]=strtod(data, &data);
В описании на эту функцию сказано следующее:
Цитата:
strtod stops reading the string at the first character that cannot be interpreted as an appropriate part of a double value.

If endptr is not null, strtod sets *endptr to point to the character that stopped the scan (*endptr = &stopper). endptr is useful for error detection.


То есть в endptr должен помещатся указатель на первый символ, который нельзя интерпретировать как часть числа.

При использовании компиляторов Borland C++ Builder 5 & 6 все ОК, при использовании Watcom C/C++ 11.0 - тоже. Все ок, 10-мегабайтные таблицы грузятся на раз-два. :) Но стоило мне откомпилить прогу в VC++ 6.0 - скорость загрузки упала неимоверно! Как выяснилось потом, реализация этой функции в Microsoft Visual C++ сделана так, что там сначала вызывается strlen(ptr), дабы определить длину строки :) . Понятно - если строка длиной в 10 миллионов символов, это несколько замедлит работу.. :)

 Профиль  
                  
 
 
Сообщение22.01.2006, 15:46 


27/11/05
183
Северодонецк
to Sanyok:

ваш код x[i]=strtod(data, &data); не совсем корректен. Если потом надо будет освобождать
память, то data уже безнадежно испорчен и free отработает неверно. Если память не освобождать - ошибки нет, но есть мусор. Поэтому для извлечения очередного плавающего
числа необходима дополнительная переменная, начальное значение которой равно data.

 Профиль  
                  
 
 
Сообщение22.01.2006, 16:11 
Заслуженный участник
Аватара пользователя


12/10/05
478
Казань
Да, конечно, тут нужно ввести временную переменную, например так:
Код:
char *tmp = data;
double *tmpx = x;
while(N--)
     *tmpx++ = strtod(tmp, &tmp);

Я просто торопился, когда набивал и старался, что бы был понятен общий смысл. Тот пост и так оказался для меня слишком длинным :)

 Профиль  
                  
 
 
Сообщение22.01.2006, 18:12 


27/11/05
183
Северодонецк
to Sanyok:

и как же вы боролись с неэффективностью strtod?

 Профиль  
                  
 
 
Сообщение22.01.2006, 19:51 
Заслуженный участник
Аватара пользователя


12/10/05
478
Казань
Я как правило, не пользовался компиляторами от Microsoft. Это - самый верный способ. :) Ну, а если серьезно, то мне для ускорения пришлось написать нечто вроде:
Код:
double mystr2d(char *ptr, char **pptr)
{
     while(isspace(*ptr))
          ptr++;
     char *ptr2=ptr;
     while(*ptr & !isspace(*ptr))
          ptr++;
     *ptr = 0;
     double tmp = strtod(ptr2, &ptr2);
     *ptr = ' ';
     return tmp;
}

 Профиль  
                  
 
 
Сообщение22.01.2006, 22:48 
Заслуженный участник
Аватара пользователя


17/10/05
3709
:evil:
Sanyok писал(а):
Продолжим? Я бы хотел заодно еще услышать и об ошибках, обнаружение которых доставило максимум хлопот. Иначе говоря, от том, чего делать нельзя. :) (Но то, что этого делать нельзя, на первый взгляд, неочевидно)

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

Пара стратегий, как избегать ошибок. (1) Внимательный анализ "соревнований" (racing condition). Ошибки проявляются иногда предельно редко, и очень не стабильны. Последствия -- от странно до катастрофических. (2) Четкое выделение атомарных операций. Здесь, по опыту, важно понимать, что сегодняшний высокий приоритет завтра может оказаться низким, со всеми вытекающими последствиями. (3) Внимательный анализ результатов теста, направленный на отделение правильных результатов от правдоподобных. Грубо говоря, отличит ли тест $\frac{\sin x}{x}$ от $\frac{x}{\tg x}$ для малых $x$ (математически очевидно -- вопрос при тестировании, и анализе результатов прогона теста). Я слишком часто видел, как люди удовлетворяются правдоподобными. Почти единственный способ -- подсчитать руками, и сравнить.(4) Инициализация данных. Неинициализированные данные в С/С++ -- едва ли не больший бич, чем указатель за пределами массива, и искать тяжелее... Оно, конечно, немного замедляет программу -- обнулять все подряд, зато поведение программы стабильно. (5) отслеживание ошибок округления. Я приведу примеры с фильтрами. Тут две ипостаси -- малое изменение сигнала просто теряется Батервортом первого порядка (и в результате, не накапливается в выходе). Другая сторона медали -- бегущее среднее для сильно меняющейся величины ($\sin \omega x$) может начать накапливать ошибку в аккумуляторе. И выдавать несуществующий сдвиг сигнала, отличный от нуля... (6) следить за арифметикой. Всегда можно забыть умножить на нужную константу -- я, например, обещал пару стратегий...

 Профиль  
                  
 
 
Сообщение22.01.2006, 23:22 
Заслуженный участник
Аватара пользователя


12/10/05
478
Казань
Спасибо и на этом. Я постараюсь привести свои ошибки (которые сейчас кажутся очень глупыми), но завтра, когда высплюсь :)

 Профиль  
                  
 
 
Сообщение27.01.2006, 09:14 
Заслуженный участник
Аватара пользователя


12/10/05
478
Казань
Я уже в свое время упоминал о такой проблеме (как-то писал про графики). Скажем , есть корзина. В энту корзину можно складывать яблоки (это к примеру :) ). То есть энта корзина потом становится собственником вложенного объекта (яблока) и может проделывать с энтими яблоками то, что они ей позволют :) Все хорошо, пока предметы собственности (яблоки) небольшие, и мы их можем добавлять в корзину просым копированием:
Код:
   TBasket *basket = new TBasket;
   ...

   ...
   while(N--)
   {
       TApple apple;
       ....
       basket->add(apple);
   }


То есть в basket помещается копия объекта.
Мне в аналогичном случае с графиками пришлось иметь дело с объектами TChart и TLineSeries (это компоненты, входящие в состав C++ Builder). TChart выступает в роли корзины, а TLineSeries - в роли яблока. :) Создавать сначала целиком TLineSeries, потом его копию, потом удалять исходный объект накладно, поэтому процедура добавления, реализованная в TChart просто добавляет к себе указатель на объект типа TLineSeries. Я об этом догадывался, но однажды, увлекшись написал следующее:

Код:
MyProc(TChart *chart, ...)
{
    TLineSeries ser;
    .
    // Тут полно строк
    .
    chart->AddSeries(&ser);
    .
    // Тут еще больше :)
    .
    .
}

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

 Профиль  
                  
 
 
Сообщение11.02.2006, 01:38 
Аватара пользователя


21/10/05
100
Одинцово
bekas писал(а):
Аналогичные воспоминия о том, как программировали в далеком прошлом. При осваивании
ЕС-совских машин в студенческие годы у нас была суровая практика, когда отдаешь
колоду перфокарт, и для исправления программы у тебя всего несколько попыток
по набивке исправлений. Умельцы умудрялись изобретать свой собственный
мини-перфоратор или, в крайнем случае, пользовались бритвой для вырезания
отверстий. Тут уж над алгоритмом подумаешь сто раз, прежде чем что-то напишешь.
Думать заставляло и отсутствие интерактивных отладчиков - только распечатка
в контрольных точках позволяла понять поведение программы...

И отверстия вырезали и дырочки забывали :) Потом все это копировалось на перфораторе - стоял такой в свободном доступе для студентов (еще от машин М20). Это было чудо бронетанковой промышленности СССР. Когда он работал, все здание тряслось.
Потом образовывалась колода из перфокарт высотой до 50 сантиметров, перевязывалась подтяжками от брюк и в таком виде сдавалась.
А самое интересное происходило тогда, когда из этой колоды выпадала одна перфокарта :) Какое разнообразие вариантов! Среди студентов ходили байки о неком маньяке, который только тем и занимался, что перемешивал такие колоды. Но не разу не был отловлен.

 Профиль  
                  
 
 
Сообщение12.02.2006, 01:53 


29/05/05
143
Debiloid писал(а):
как более адекватно и понятно перевести на русский "literate programming" - не знает никто.


Lingvo 10 с LingvoComputer-словарём сказала, что "literate programming" - это "грамотное программирование, культурное программирование".

 Профиль  
                  
 
 
Сообщение12.02.2006, 02:38 


27/11/05
183
Северодонецк
Я бы не очень доверял всяким Lingvo. Если хотите повеселиться, попробуйте
через Lingvo или любой другой переводчик выполнить двойной перевод:
с русского на английский, а потом этот же текст с английского на русский.
Для примера можно взять незабвенные строки Некрасова:
"Однажды в студеную зимнюю пору я из лесу вышел..." и так далее еще строк 15.
Для большего эффекта можно усилить цепочку РУССКИЙ-АНГЛИЙСКИЙ-НЕМЕЦКИЙ-РУССКИЙ

Автоматические переводчики худо-бедно справляются с простыми текстами, а вот с шедеврами (в истинном смысле этого значения) русского языка у них мало что путного выходит. Речь идет не о шедеврах типа "Зайка моя, я твой тазик", а о произведениях
Пушкина, Лермонтова и т.д.

 Профиль  
                  
 
 
Сообщение12.02.2006, 02:47 
Аватара пользователя


20/01/06
64
оттуда
bekas писал(а):
...Если хотите повеселиться, попробуйте
через Lingvo или любой другой переводчик выполнить двойной перевод:
с русского на английский, а потом этот же текст с английского на русский.
Для примера можно взять незабвенные строки Некрасова:
"Однажды в студеную зимнюю пору я из лесу вышел..." и так далее еще строк 15...

Если 2 человека-переводчика не будут знакомы с этими "незабвенными строками", то результат двойного перевода будет отличаться от оригинала. Особенно, если
Цитата:
усилить цепочку

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 149 ]  На страницу Пред.  1, 2, 3, 4, 5, 6 ... 10  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group