- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
do
{
count++;
Xt=X;
if (ii==1)
{
X= dichotomia(a,b, E);
fprintf(bnf, "%lf;\n", Xt);
}
else
{
if (ii==2)
{
X=newton(X, E);
fprintf(bnf, "%lf;\n", Xt);
}
else
{
if (ii==3)
{
X=sekuschich(X, b);
fprintf(bnf, "%lf;\n", Xt);
}
else
{
if (ii==4)
{
ii==1;
ii==2;
ii==3;
}
}
}
}
printf("X=%lf\n", X);
if(Func(X)*Func(a)>0)a=X;
else b=X;
}
while(fabs(X-Xt)>=E);
В общем лаба на численые методы поиска корней.
После того как я предоставил няшный, полностью удовлетворяющий условиям, после проверки меня попросили "сделать как у парней", и вот участок их высера
p.s. форматирование сохранить не удалось, да и там совсем бы ничего понятно бы не было
bormand 09.07.2012 10:13 # +4
Печально. Вот так у нас и готовят будущие кадры...
maksim_ovcharik 09.07.2012 10:33 # 0
и парни которые написали этот код очевидно даже не разбирались в сути методов и в тз, так как ошибок там очень много и их программа работает не правильно.
bormand 09.07.2012 10:40 # +3
У нас тоже такая фигня была. Причем "5 курсов до тебя решали, все нормально было, а ты не можешь, иди переделывай". Но я препода тогда таки смог убедить, что косяк в задании...
movaxbx 09.07.2012 16:47 # 0
Ох, как я Вас понимаю.
Так и не доказал, но зачет все же получил.
Fai 09.07.2012 16:49 # 0
movaxbx 09.07.2012 17:12 # 0
defecate-plusplus 09.07.2012 17:23 # +2
interested 09.07.2012 17:31 # 0
Любой метод поиска действительного корня прежде всего требует локализовать знакопеременный отрезок.
График -- один из способов локализации.
Тем не менее, в существование лабыря, который даёт задачи со знакопостоянным отрезком, на котором ещё нужно что-то локализовывать -- не верю.
bormand 09.07.2012 19:01 # 0
Это как вампиры - вы в них не верите, но они существуют.
eth0 09.07.2012 19:46 # 0
Lure Of Chaos 09.07.2012 23:04 # 0
видели?
movaxbx 09.07.2012 20:31 # 0
Только это не поиск корней уравнения был, а какой-то итерационный матан с дифурами, уже не помню.
defecate-plusplus 09.07.2012 16:56 # +5
defecate-plusplus 09.07.2012 10:45 # +2
ну и "где тут %username%, с++"?
bormand 09.07.2012 11:06 # +1
Kirinyale 09.07.2012 11:31 # 0
struct II
{
int ii_;
II() {}
II(int ii): ii_(ii) {}
bool operator == (int n) const
{
if (ii_ < n)
return false;
if (n==1)
{
X= dichotomia(a,b, E);
fprintf(bnf, "%lf;\n", Xt);
}
else if (n==2)
{
X=newton(X, E);
fprintf(bnf, "%lf;\n", Xt);
}
else if (n==3)
{
X=sekuschich(X, b);
fprintf(bnf, "%lf;\n", Xt);
}
return (ii_ < 4) && (ii_ == n);
}
} ii;
std::cin >> ii.ii_;
defecate-plusplus 09.07.2012 11:39 # +3
Kirinyale 09.07.2012 11:42 # +1
Так лучше? :)
defecate-plusplus 09.07.2012 11:46 # +2
если это шутка, то неудачная
Kirinyale 09.07.2012 14:59 # +1
Я, правда, не проверял, мне лень...
roman-kashitsyn 09.07.2012 15:04 # 0
Kirinyale 09.07.2012 15:08 # 0
roman-kashitsyn 09.07.2012 15:16 # 0
interested 10.07.2012 08:01 # 0
Возможно, лабырь не понимал программы, которую написал студент и попросил переписать её "вот в таком китайском виде".
Если бы это была задача именно на управление ресурсами на упрощение сопровождения и т.д., то написание "правильного и симпатичного кода" стояло бы на первом месте.
А если это конкретно задача для семинаров по выч.матам, то здесь и приоритет другой. И так же как до 16 лет права не выдают, даже если всё подросток может, так же и в университете до 4го курса не будут разрешать писать "как тебе удобно", а будут требовать "как удобно семинаристу".
maksim_ovcharik 11.07.2012 17:01 # 0
guest 22.06.2013 11:58 # 0
defecate-plusplus 09.07.2012 15:53 # −1
ты правда думаешь, что логику стоит засовывать в bool operator == (int) const?
или это гипотетическое предположение, как этот класс пристроить к вышеуказанному коду? но они несовместимы
> Если 1,2,3 - решаем одним способом. Если 4 - всеми тремя
это можно описать гораздо более элегантным способом
например, массив функций, из которого вызовется либо i-я функция, либо в цикле пробежится по всем
Kirinyale 09.07.2012 15:58 # +1
> как этот класс пристроить к вышеуказанному коду?
Именно!
Ясен хрен, что это всё бред и можно проще и вменяемее. Но переписывать на работе чью-то лабу по-человечески мне неинтересно. Придумать, как заставить работать извращённый говнокод, не меняя его, а только добавляя свой вместо пропущенных участков - совсем другое дело. :)
А в чём именно я несовместимость проглядел, кстати?
defecate-plusplus 09.07.2012 16:01 # −1
двойной вызов функции dichotomia
Kirinyale 09.07.2012 16:11 # +1
defecate-plusplus 09.07.2012 16:28 # 0
http://ideone.com/W6rNA
Kirinyale 09.07.2012 16:33 # +1
roman-kashitsyn 09.07.2012 16:15 # 0
Мсье знает толк!
bormand 09.07.2012 17:23 # +7
Решение нужно было засунуть в оператор double.
defecate-plusplus 09.07.2012 17:29 # +5
причем в зависимости от количества приведений к double выдавать 1..N корень:
roman-kashitsyn 09.07.2012 22:45 # +4
interested 10.07.2012 07:16 # −2
Скажем, привидение типа указателя -- это было бы странновато, потому что все они на деле одинаковые только контракты разные и знать о контрактах может только система, которой мы заранее сообщаем.
А если это привидение объектов, то здесь может быть сколь угодно сложная логика.
Например приведение матрицы в число и числа в матрицу может быть весьма нетривиальным в зависимости о задачи.
Fai 10.07.2012 08:21 # 0
......( 0 0 0 )
1 = ( 0 1 0 )
......( 0 0 0 )
quest 10.07.2012 09:15 # 0
Fai 10.07.2012 09:28 # 0
Возникает неоднозначность - кто знает, какую туда логику автор засунул?
quest 10.07.2012 09:50 # +3
interested 10.07.2012 09:43 # −1
число в матрицу и обратно по метрике,
число в матрицу и обратно как максимальное собственное число,
число в матрицу и обратно как определитель.
Строго говоря любое отображение -- это и есть преобразование типа, а отображение может быть очень сложным. С тем же уравнением. Если задача каким-то образом требует отображения, например, полиномов в "наибольший действительный корень", то это отображение логично разместить в операторе приведения уравнения к double или float.
defecate-plusplus 10.07.2012 09:53 # +1
вместо метода с говорящим названием делать подло в операторе приведения к типу
interested 10.07.2012 12:19 # +1
Что, простите, тут скрывает действие? Что может быть не ясно?
defecate-plusplus 10.07.2012 12:32 # −1
if (matrix > 1.)
std::cout << "sqrt of matrix value " << (double)matrix << " is " << std::sqrt<double>(matrix) << std::endl;
ведь на форуме сказали, что с++ быстрее дельфи, опять соврали!
interested 10.07.2012 13:01 # +1
defecate-plusplus 10.07.2012 13:05 # +1
нет пути
interested 10.07.2012 13:12 # +1
defecate-plusplus 10.07.2012 12:37 # −1
> число в матрицу и обратно как максимальное собственное число,
> число в матрицу и обратно как определитель.
> Что, простите, тут скрывает действие? Что может быть не ясно?
вот и я о том же, за каким х в приведении типа скрывать какое то действие, чтобы обязательно было что то не ясно?
для собственного числа и определителя для класса матрицы обязаны быть методы eigen_value и det, а не тайные приведения к double
interested 10.07.2012 13:04 # 0
Что не ясно?
>обязаны быть методы eigen_value
Вовсе не обязаны. Это существенно зависит от задачи.
И вообще никто никому ничего не обязан, если на то нет хотя бы приличного императива.
TarasB 10.07.2012 13:36 # +6
Крестоблядство какое-то предлагает
bormand 10.07.2012 15:34 # 0
Тарас, ты как нельзя прав...
Fai 10.07.2012 13:38 # 0
Кто его знает что произойдёт?
1. В-лоб - т.е. переносим биты без изменений.
2. Округление в меньшую сторону.
3. Округление в большую сторону.
4. Округление до 0.
5. Округление до ближайшего целого.
Даже такое простое преобразование настолько многогранно, стоит ли злоупотреблять возможностью перегрузки и реализовывать в операторах приведения логику.
Всё-таки если пишете myObject.toInt() то хотите в итоге получить числовое представление числа, а не что-то другое. Если числового представления нет или оно не однозначно - не нужно делать метод toInt().
А операторы приведения типов это как раз аналоги методов toType().
TarasB 10.07.2012 13:44 # +3
Я бы так сказал:
> Неявное приведение даже double -> int - зло.
Больше скажу, наоборот - тоже.
Fai 10.07.2012 17:27 # 0
defecate-plusplus 10.07.2012 13:45 # −1
стандарт знает, никакого округления, только отсечение дробной части
проблемы только если результат не способен хранить в себе в точности полученное обрезанное значение
4.9 Floating-integral conversions
1. An rvalue of a floating point type can be converted to an rvalue of an integer type. The conversion truncates; that is, the fractional part is discarded. The behavior is undefined if the truncated value cannot be represented in the destination type.
Fai 10.07.2012 13:50 # +1
Я показал насколько неоднозначна ситуация с простым приведением.
А человек тут хочет приведение из числа в матрицу сделать и обратно.
Свой стандарт будет писать?
interested 10.07.2012 13:55 # 0
TarasB 10.07.2012 14:00 # +2
interested 10.07.2012 14:08 # −2
Ну... или можешь в какую-нибудь менее интеллектуальную профессию перекинуться ;) Глядишь, всё на своих местах останется.
defecate-plusplus 10.07.2012 14:06 # −1
по моему, преобразование double -> integer очень интуитивно и даже не требует документации
а преобразование матрица - не матрица обычно крайне неинтуитивно
теперь попробуйте вышеприведенный код с матрицами понять без комментариев
interested 10.07.2012 14:11 # −1
Приучен с детства.
Вопрос закрыт.
Fai 10.07.2012 15:02 # +2
Писать доки, комментарии на 3 экрана к каждой функции только из-за желания перегрузить оператор?
Глупости.
interested 10.07.2012 15:12 # −3
Код сам себя задокументировал: я привожу матрицу в число.
Вопрос закрыт.
TarasB 10.07.2012 15:58 # +1
Представь, что я сделаю метод OpenQuestion, который на самом деле банит всех участников темы, и напишу в документации "этот метод банит всех участников темы". Чё, нормально?
roman-kashitsyn 10.07.2012 15:59 # +3
interested 10.07.2012 16:12 # −1
Если у тебя есть класс PriorityQueue, то это ни о чём не говорит, кроме того, что это PriorityQueue. А с какой сложностью это выполнено, как это реализовано конкретно, нужно либо в исходный код лезть, либо читать доки.
>Открываю вопрос обратно.
Open failure.
TarasB 10.07.2012 16:24 # +1
interested 10.07.2012 16:29 # −4
TarasB 10.07.2012 16:34 # +1
Называть вычисление детерминанта приведением к числу - это и есть заговариваться.
interested 10.07.2012 16:37 # −5
Я нигде не писал, что нужно располагать вычисление детерминанта в приведении к числу.
defecate-plusplus 10.07.2012 16:40 # 0
> число в матрицу и обратно как определитель.
> логично разместить в операторе приведения
http://govnokod.ru/11383#comment146305
определитель != детерминант?
interested 10.07.2012 16:45 # −1
Здесь ничего не сказано о том, где следует размещать логику вычисления детерминанта.
Не надо додумывать, надо читать, что написано. Не ясно -- задайте вопрос..
defecate-plusplus 10.07.2012 16:47 # +1
TarasB 10.07.2012 16:47 # +3
Vindicar 11.07.2012 15:24 # 0
Если для точки (которая, как известно, вектор) определить эту перегрузку чтобы она возвращала евклидову длину вектора, то это тоже будет неправильно?
Для справки: есть и перегрузки для приведения к int и float.
TarasB 11.07.2012 15:44 # +2
roman-kashitsyn 10.07.2012 16:49 # 0
Fai 10.07.2012 17:29 # 0
Отрываю вопрос.
Закрываю вопрос.
...
interested 10.07.2012 13:48 # −1
Прошло время и я понял, что никакого секрета нет.
roman-kashitsyn 10.07.2012 10:23 # +6
За такую логику нужно гвоздь в голову забивать. Класс матрицы/уравнения не должен содержать в себе алгоритмов решения - алгоритмов обычно много и гораздо удобней отделять их от задачи, которую они призваны решить. Это позволить легко выбирать алгоритм в рантайме, например. А приведение к типу вместо явного вызова решаюшей процедуры - грязный хак, который могут придумать разве что самоуверенные студенты "по приколу", чтобы продемонстрировать самим себе, что они могут переопределять приведение типа в таком гибком и хардкорном C++.
interested 10.07.2012 12:17 # −4
Не надо приписывать мне то, чего я не говорил.
Если вам требуется найти решение, то поиск решения передвигать в привидение типа действительно глупо. Но!
Если вам нужно отображение, то это и есть приведение типа, получение из A -> B.
Можно, конечно, применять "говорящие методы" .toString() .toInt() .toDouble() .toSomethingIHaveInMind().
Однако, в C++ есть действительно удобное средство для таких операций.
А вот, скажем, в Java нет. Пользуемся "говорящими методами".
roman-kashitsyn 10.07.2012 12:32 # +3
>> максимальное собственное число
Нахождение этих величин - весьма нетривиальная задача, запихивать решение которой в класс матрицы - очень глупо.
> любое отображение -- это и есть преобразование типа
Отображение связано с преобразованием типа лишь косвенно. Можно легко найти примеры функций, на входе и на выходе которых один и тот же тип (id x = x).
По сути любой алгоритм является отображением (функцией), поэтому не понятно, с какой стати вы проводите различие между поиском решения и отображением.
interested 10.07.2012 13:01 # −3
Привидение типа -- ясный контракт получения из A в B.
Если вы хотите показать, что это контракт именно решения, а не отображения, пишите метод в алгебру.
Согласен, что привидение типа специфическое отображение из алгебры в алгебру, и потому оно и может быть сложным, и потому для него используются специальные конструкции, поясняющие, что происходит.
roman-kashitsyn 10.07.2012 13:16 # +2
Нихера он не ясный. Даже способ приведения строки к числу отличается практически во всех динамических языках с нестрогой типизацией. А уж приведение матрицы к числу у меня, к примеру, вызывает когнитивный диссонанс.
interested 10.07.2012 13:27 # 0
Контракт прозрачен: положи А, получи B.
Положи 10р. --> получи билет.
Если вам нужно узнать как же это происходит, то это другой вопрос. Читаем документацию. И, скорее всего, подобные вещи ясны из контекста самого кода. Если вы используете библиотеку, которая делает преобразования СТО, то, почти наверняка, преобразование из числа в матрицу -- это создание диагональной матрицы по метрике Минковского.
roman-kashitsyn 10.07.2012 13:30 # +3
А вот в обратную сторону неинтуитивная жопка получается.
defecate-plusplus 10.07.2012 13:35 # +3
ты это специально сказал, ведь, да?
матрицы в число через приведение типов - теперь понятно, почему пациент так отстаивал принудительное double a = static_cast<double>(b); везде, где можно
roman-kashitsyn 10.07.2012 13:38 # +3
именно
interested 10.07.2012 13:38 # −2
Это уже конкретный конструкторский приём. А сама абстракция -- отображение. Я точно также могу сказать, что преобразование матрицы в double -- просто конструирование числа с матрицей в качестве аргумента.
>А вот в обратную сторону неинтуитивная жопка получается
Мне приходилось работать с библиотекой для газодинамики с дефлограцией, где было преобразование матрицы в double, возвращавшее оценку наибольшего собственного числа.
И это было написано в доках к библиотеке.
roman-kashitsyn 10.07.2012 13:44 # +1
interested 10.07.2012 13:54 # 0
Когда не просто A -> B, но и какой-то медиатор нужен.
А каст -- это точно из А в B.
eth0 10.07.2012 14:08 # +2
bormand 10.07.2012 16:03 # 0
Если вам нужно использовать все 3 способа в одном модуле, а они помещены в оператор преобразования типа - каким хуем вы будете выбирать тот вид преобразования, который нужно провернуть в данном случае?
interested 10.07.2012 16:15 # −1
Ещё раз повторю.
Если вам нужно предоставить контракт именно получения детерминанта, то и стройте контракт детерминанта.
Если вы хотите предоставить контракт преобразования матрицы в число, то вы предоставляете именно этот контракт, который бесшовно выражает в С++ преобразованием типа.
>Если вам нужно использовать все 3 способа в одном модуле
Я буду использовать такую библиотеку, которая предоставляет три различных контракта.
TarasB 10.07.2012 16:23 # +3
АХАХАХ посоны прикиньте - оператор привидения! Чувак такой за пультом сидит и привидение на радиоуправлении летает!
interested 10.07.2012 16:34 # −1
Вызови static_cast и будет тебе явно.
bormand 10.07.2012 16:57 # +3
Простите, но вы хуй.
interested 10.07.2012 17:01 # −2
bormand 10.07.2012 17:04 # +2
interested 10.07.2012 17:13 # −2
Преобразование матрицы в число вовсе не мифическое, это два.
Эти 50 постов продолжаются потому, что каждый раз, когда я говорю, что тарелка красная, мне доказывают, что она круглая. Я постоянно пишу, что прекрасно понимаю, что она круглая. И, всё-таки, она красная.
Это три.
bormand 10.07.2012 16:57 # +1
Ни одному вменяемому человеку не придет в голову "преобразовывать матрицу в число". Способов такого преобразования много. У каждого способа есть название и соответствующий контракт, которым и нужно пользоваться.
> Я буду использовать такую библиотеку, которая предоставляет три различных контракта.
Я тоже. И это будут методы, а не операторы приведения типов (т.к. 3 оператора приведения для одних и тех же типов описать невозможно).
interested 10.07.2012 17:06 # −1
Во-первых, придёт, и не одному.
Во-вторых, это не всегда соответствие какому-то контракту иному. Например тоже приближение максимальным собственным числом. То что, значение близко к характеристическому числу, не значит, что оно равно. Логика можно быть замысловатая, но использующая eigen_value().
Не говоря уже о том, что можно себе представить инверсию управления на этом операторе. Это, конечно, фантастика, я такого не видел. Но представить можно.
bormand 10.07.2012 17:15 # +2
Proof or GTFO. Причем такой пруф, чтобы автор говорил именно о "преобразовании матрицы в число", а не "вычислял определитель" или "вычислял наибольшее собственное значение".
> Логика можно быть замысловатая
У этой логики есть название? Есть. Значит это уже не абстрактное "преобразование матрицы в число", а какое-нибудь "преобразование Пупкина" или "алгоритм Зихтельберга".
> Но представить можно.
Можно. А еще можно ходить по раскаленным углям и протыкать себя саблями. Но нужно ли это?
interested 10.07.2012 17:28 # −1
Если бы я мог дать кусочек кода и тем паче ссылку, я бы это сделал.
Здесь речь не идёт о какой-то супер-пупер open-source библиотеке.
О чём конкретно шла речь, я писал выше. Трёх реальных случаях из моей жизни.
> Но нужно ли это?
В каждом конкретном случае каждый метод делается с определённой целью и вряд ли абстрактной.
Преобразование матрицы в число, с которым я сталкивался, сделано исключительно для удобного общения одной части библиотеки с другой.
Конкретно, сделано было с целью возможности подсунуть состояние, представленное матрицей, в методы приблизительной оценки.
Fai 10.07.2012 17:34 # 0
interested 10.07.2012 17:58 # −1
И удобства эксплуатации. Внутри моего куска кода, под моим именем нет неявных конструкторов. Но в случае с выхлопом "наружу", мнение окружающих важно.
bormand 10.07.2012 17:37 # +3
Эти случаи назывались "поиск определителя", "вычисление метрики" и "вычисление наибольшего собственного значения"? Так какого ж ... вы пишете, что это абстрактное "преобразование матрицы в число". Я более чем уверен, что назывались они не toNumber(), и что в комментариях к этим методам вы писали их корректные названия, а не "Преобразование в число. Подробности в документации"...
> В каждом конкретном случае каждый метод делается с определённой целью и вряд ли абстрактной.
Полностью согласен. Но у вас, простите, по классу матрицы на каждую библиотеку? Матрица у которой оператор приведения возвращает наибольшее собственное значение, матрица, у которой оператор приведения возвращает определитель... Вот такое вот ооп...
TarasB 10.07.2012 17:46 # +1
double d = (double)(MatrixWhichCastsToDoubleAsDeter minant)M;
Fai 10.07.2012 17:50 # 0
fxd
TarasB 10.07.2012 18:46 # +1
bormand 10.07.2012 17:55 # +1
Ну тогда шаблоны для "приведения":
interested 10.07.2012 17:49 # −1
Эти случаи никак не назывались. Речь шла о том, что внутри логики преобразования одного в другое может быть запрятана более сложная логика. Включавшая в себя вычисление определителя или оценку собственного числа.
Так придумали наши американские друзья. Это сначала было несколько непривычно, но потом всё стало понятно.
Относительно преобразования числа в матрицу по метрике, это была удобная программа для работы с преобразованиями СТО.
Относительно детерминанта, что-то для порядка вычисления. Тоже для удобства навешено на оператор приведения, на случай, если логика изменится.
Fai 10.07.2012 18:03 # 0
bormand 10.07.2012 18:07 # 0
Привет, Perl! Там так и есть.
interested 10.07.2012 18:16 # −1
То есть, внутри преобразования используются иные методы, чтобы "удовлетворительно", с точки зрения поставленной задачи, преобразовать одно в другое.
Я, в проекте, с которым работаю, использую преобразование уравнения в приближение к локальному минимуму.
bormand 10.07.2012 18:25 # +1
Ну зачем, зачем принимать решения, которые снижают понятность проекта ради копеечной выгоды... Ну неужели там тысячи поисков этого локального минимума, и писать eq.localMin() уже невмоготу...
Самое плохое тут - теряется универсальность решения. Допустим, в соседнем проекте мне надо было бы искать локальные максимумы этого уравнения - я бы добавил в этот класс еще один метод, и использовал бы эту библиотеку в двух проектах... А здесь как? Копипастить ее в другой проект и переделывать оператор? Ну не понимаю я таких "оптимизаций"...
interested 10.07.2012 18:36 # −1
Это вот как раз та самая идея, подсмотренная у программистов Crysler, когда я ещё учился.
Есть у меня набор уравнений и есть некая функция.
Функция принимает массив double и выплёвывает оптимальный double.
Я преобразую уравнения в double, используя некий "эмпирический" алгоритм из компонент оценки минимума. Зашарашиваю в эту супер-пупер функцию, которая выплёвывает мне оптимальный double. Нахожу несколько уравнений с близкими double, потом повторяю, пока не получится самое удачное к близкому.
Вот тот минимум и даёт мне "хорошую" характеристику системы.
bormand 10.07.2012 18:40 # 0
Ну а почему это должно быть оператором (double) а не методом approximate()?
interested 10.07.2012 18:47 # −1
Это действительно мог быть и метод с "говорящим названием" .findEmpiricDoubleApproximation();
Но суть в том, чтобы получить из уравнения число, чтобы вбросить в массив. И я никак не вижу, что это улучшит прям читаемость кода. И вроде бы как люди согласны.
То есть, это на мой взгляд оно самое: абстрактное отображение. Ведь я могу туда что угодно запихнуть. Минум. Максимум. Коэффициен ряда. Главное, чтобы double был, чтобы его в массив свалить.
interested 10.07.2012 18:54 # 0
Я не хочу, чтобы человек, который потом будет пользоваться этим или подключать куда-нибудь, хоть что-то предполагал о том, как это происходит. А то ещё начнёт где-нибудь переиспользовать эти числа по иному назначению.
-- Ага, раз минимум, буду его пользовать. А потом в новой версии пересоберётся это дело с новым алгоритмом -- и чепец.
bormand 10.07.2012 19:02 # +1
Прочитав название метода empiricApproximation() он поймет только то, что это каким-то образом вычисляет приближение, и не более того. Что вам и нужно. В документации к методу можно описать, что возвращаемое значение зависит от реализации, и может измениться в любой момент. Я не вижу улучшения инкапсуляции от использования оператора (double).
> И я никак не вижу, что это улучшит прям читаемость кода.
Да ну бросьте:
Неявное преобразование - трудно заметить.
Явный статик_каст - заметен, но не показывает цели этой операции, да и длиннее чем empiricApproximation().
interested 10.07.2012 19:46 # −2
Всё же, мне кажется, что здесь есть ещё своеобразный "психологический" момент.
Когда я пишу метод, то это больше напоминает какое-то свойство алгебры, выраженное в терминах другой.
А конверсия показывает, что тут происходит нечто более сложное.
Свойств, выраженных методами, может быть много: approximation1(), approximation2(), ... А конверсия одна.
Конверсия, вообще говоря, говорит о том, что в этом месте используется какая-то тесная связь между алгебрами, вероятно, какая-то внутренняя информация и об источнике, и о приёмнике, вообще говоря.
Я полагаю, что подобные вещи, вроде сброса состояния в число, для каких-то сторонних оценок, ближе именно к конверсии, а не к получению свойства в терминах числа.
Конверсия типа обладает, своего рода, "внутренне присущими" свойствами, которые присутствуют и на уровне проектирования, на уровне алгебр, когда кода ещё нет. По этой причине конверсия кажется прямым переходом от проекта к коду.
Много слов... И смысл при этом, действительно, размыт. Я понимаю.
Тут нужно думать о изоморфизме между отношениями на уровне моей задачи и отношениями между структурами уже в языке программирования.
bormand 10.07.2012 20:50 # +2
А мне вот, наоборот, кажется, что конверсия должна быть простой и интуитивной.
> Я полагаю, что подобные вещи, вроде сброса состояния в число, для каких-то сторонних оценок, ближе именно к конверсии, а не к получению свойства в терминах числа.
Да нет. Это именно свойство уравнения - некая оценка, полученная на основе его изучения. Преобразованиями тут и не пахло. Все-таки математик, имхо, напишет "вычисляем меру" или "получаем эвристическую оценку", но никак не "преобразуем это уравнение в число".
interested 10.07.2012 21:15 # 0
Может быть это вопрос уже конкретно стиля. Я не утверждаю, что прям вот так нужно делать. Но мне кажется это более логичным, а вот вам нет.
Если бы это была "мера", то это действительно был бы метод. Тому можно много привести доводов.
А вот такой "финт" уже вызывает сомнения. Фактически я использую его для "склейки" каких-то разных участков кода. То есть, это такой "проектный шов", "бесшовно переходящий в кастинг".
Я бы уже закрыл этот вопрос. Вроде бы понятно, что все всё поняли. Я хотел указать, что задачи бывают, когда нужно бывает один тип сбросить в другой, чтобы как-то пооперировать с ним в другой алгебре, и, не исключено, что даже как-то "ожидаемо" его восстановить. И в некотором случае даже преобразование в double сложного типа может казаться людям логичным.
Да. Подобная многословность, к сожалению, приводит к усложнению сопровождения. Но тут уж... Закон сохранения халявы: или применять много разных методов даже для близких ситуаций, но тогда придётся постоянно оглядываться; или вам это не нужно, но зато всё много более предсказуемо.
bormand 10.07.2012 21:24 # 0
С этим я полностью согласен, постом ниже я как раз привел несколько примеров, в которых такая конверсия имеет смысл.
> Я бы уже закрыл этот вопрос.
Ок.
bormand 10.07.2012 21:10 # +1
Правильная мысль...
К примеру между двумя представлениями уравнений есть изоморфизм - здесь оператор преобразования типа очень даже к месту.
К месту оно было бы, возможно, и при преобразовании вектор-столбца в вектор-строку. (Хотя тут спорно).
Идеально вписывается конверсия и в случай преобразования трехчлена в многочлен.
Но вот между уравнением, и его решением, тем более приближенным, лежит метод его решения. Что как-бы намекает нам на то, что здесь нужно использовать метод, а не преобразование типа.
bormand 10.07.2012 18:34 # 0
Продолжение:
Допустим, я хочу указывать точность этого самого приближения... куда мне ее передать? Вот умел бы статик каст принимать параметры, и передавать их оператору...
Fai 11.07.2012 05:50 # 0
Например:
double determinant = DeterminantCalculator( matrix );
DeterminantCalculator - конструктор. принимающий матрицу, а получаемый объект может быть преобразован в double.
С другой стороны сразу видно что это не разу не объект а простая функция.
double calculateDeterminant( Matrix m );
Что логично сделать методом класса Matrix.
А преобразование тут не причём. Его можно встроить в объект-вычислитель-определителя, но не в объект-матрица.
roman-kashitsyn 11.07.2012 08:38 # 0
> логично сделать методом класса Matrix
Логично, наверное, включить в класс некую стандартную реализацию этого метода. Но от внешних "решателей" всё равно не уйти. Дело в том, что выбор хорошего алгоритма вычисления определителя в реальной жизни зависит от свойств матрицы. И тут уж либо городить для каждого типа матрицы свой класс, что не всегда возможно, либо выносить задачу вычисления наружу.
interested 11.07.2012 09:21 # 0
Детерминант -- свойство квадратной матрицы. Как бы мы его не вычисляли, результат зависит от матрицы, а не от метода. Для человека логично ожидать, что это будет именно свойство матрицы.
Можно инжектировать оптимальный вычислитель в матрицу при конструировании или при перехвате вызова getDeterminant().
Удобно? Несомненно!
Клиент не заботится о том, что нужно вызвать какую-то там специальную функцию на матрицу. Клиент естественным образом обращается к свойству матрицы, при этом всегда, или почти всегда, получая оптимизированные вычисления.
Но на это требуются серьёзные накладные расходы на подобную кухню менеджмента.
Закон сохранения халявы: чем удобнее, тем больше накладных расходов. Ищем приемлемый компромисс.
Иногда вычисления настолько громоздкие, что подобные накладные расходы -- капля в море.
roman-kashitsyn 11.07.2012 12:18 # 0
В идеальном мире. В реальном мире для больших матриц, значения которых заданы в виде чисел с плавающей точкой, это неверно.
Тот, кто задаёт матрицу, может знать о ней больше машины (например, что она трёхдиагональная и т.п.). Некоторые довольно эффективные алгоритмы требуют симметричности матрицы, и т.п.
interested 11.07.2012 12:40 # 0
Я вижу следующее:
>Можно инжектировать оптимальный вычислитель в матрицу при конструировании или при перехвате вызова getDeterminant().
Если клиент знает о матрице больше, то он будет внедрять вычислитель в матрицу руками. Скажем, в процессе вычислений матрица всегда остаётся трёхдиагональной.
Если клиент не знает какого вида будет матрица в процессе вычисления, то можно подключить "умный оптимизатор", который будет выбирать подходящий метод, анализируя матрицу до передачи управления в getDeterminant().
roman-kashitsyn 11.07.2012 13:23 # +1
>> Как бы мы его не вычисляли, результат зависит от матрицы, а не от метода
В реальном мире детерминант внезапно становится не F[Matrix], а F[Matrix][Algorithm], т.е. зависит ещё и от метода, которым мы его считаем, и часто лишь можем указать границы, в которых он лежит.
Инжектить вычислитель при конструировании, конечно, можно, но я бы так не стал делать. Может, пользователю, работающему с матрицей, вовсе этот детерминант не интересен. Нужнен будет - пусть сам выбереть вычислитель. Явное лучше неявного. Умный оптимизатор скорее всего не подойдёт, слишком уж дорого выйдет его работа.
В общем, если бы я проектировал API для работы с линейной алгебной, Matrix бы отвечал только за доступ к элементам и базовые операции (сложение, умножение и т.п.). Сделал бы подклассы Matrix для специализации разреженных, ленточных, симметричных, ... матриц. Поиск собственных векторов/чисел/детерминанта/... были бы внешними операциями.
Повторюсь, так бы сделал я. Вариант со специализацией алгоритмов внутри подклассов Matrix в теории тоже приемлем.
roman-kashitsyn 11.07.2012 13:26 # 0
defecate-plusplus 11.07.2012 14:15 # −1
операторы можно определить как в классе, так и вне - как инлайновый бинарный оператор
т.к. нам явно понадобятся дефолтные операции, то очевидно, в базовом классе (скажем, gen) будут операторы, умеющие складывать и т.д. с другим базовым классом
для класса потомка T1, если нужно отдельно оговорить иное поведение на сложение с другим типом (в т.ч. базовым) T2, придется описать внешние бинарные операторы парой (T1, T2) и (T2, T1)
http://ideone.com/qVyn1
- одного (T1, T2) не хватит (если не будет (T2, T1), то компилятор сперва найдет (gen, T1), приведет к (gen, gen) и успокоится)
http://ideone.com/sp2TO
ну и, думаю, очевидно, что никакого полиморфизма тут работать не будет
roman-kashitsyn 11.07.2012 14:41 # +1
Помню, в универе пытался моделировать на жабе базовые математические концепции, ввёл различные типы чисел (натуральные, целые, рациональные, ...) и пытался написать для них операции сложения / вычитания / умножения / деления, которые бы имели вменяемое с точки зрения математики поведение. Желательно, чтобы всё это было типобезопасно. В общем, ситуация практически аналогичная.
Так вот, вышло всё это полным провалом. Сейчас я почти уверен, что это невозможно реализовать на Java расширяемо без унылых instanceof и кастов, ибо точный тип + неизвестен в compile time. Разве что вводить собственную систему диспетчеризации по типам. Но задача в целом нетривиальная.
Это было одной из причин, почему я заинтересовался Lisp.
defecate-plusplus 11.07.2012 14:48 # −1
но инертность производителей компиляторов и несовместимость их реализаций rtti так и не позволили продавить эту функциональность в стандарт
interested 11.07.2012 13:42 # 0
А никто вам и не предписывает устраивать API определённым образом.
Как вы с коллегами и клиентами (людьми имеется в виду, которые ваш код будут использовать) договоритесь, так и делайте.
Вы упоминали, что нужно городить много подклассов матриц или выносить "наружу".
Я представил бесшовный переход от анализа в проект, где вычисление детерминанта по прежнему принадлежит матрице, как оно было бы в реальной жизни, а все вычислительные нюансы спрятаны в сложности структуры. Конечно, по сути из матрицы вынесен метод вычисления, но так, что пользователю этот процесс может по прежнему казаться прозрачным.
roman-kashitsyn 11.07.2012 13:56 # +3
Возьмём популярный нынче OpenSource. Чтобы решить свою задачу, вы разрабатываете библиотеку, и понимаете, что она может быть полезна потенциально многим людям. С кем и что вы собираетесь обсуждать? Скорее всего, люди захотят использовать этот код совсем не тем способом, каким вы его используете, и их требования могут серьёзно отличаться от ваших.
Вам, как разработчику библиотеки, остаётся лишь детально продумать возможные варианты использования и приложить максимум усилий на выделение и ключевый несвязанных сущностей и предоставление возможности их комбинировать, желательно, лишь допустимыми способами.
Именно эти качества я и считаю наиболее важными в публичном API: наличие ярко выраженных сущностей с понятными и удобными правилами их комбинаций.
Повторюсь, против вашего подхода (наличие у матрицы свойства determinant) я особых возражений не имею, это может быть удобно в рамках некоторых задач. Но моей бы первой мыслью была "А по какому алгоритму происходит вычисление детерминанта?".
Fai 11.07.2012 16:09 # 0
Fai 11.07.2012 16:10 # 0
eth0 11.07.2012 16:32 # +1
roman-kashitsyn 09.07.2012 11:58 # +4
guest 22.06.2013 10:51 # 0
wvxvw 09.07.2012 10:46 # 0
TarasB 09.07.2012 11:00 # +2
bormand 09.07.2012 11:06 # 0
Lure Of Chaos 09.07.2012 11:18 # +3
> нормальные языки
т.е. функциональные?
zim 09.07.2012 12:04 # 0
А о каких таких языках говорит @TarasB я не знаю.
roman-kashitsyn 09.07.2012 12:09 # 0
Кто отделяет? Из известных только Haskell и отделяет, Erlang, OCaml, Lisp, Scala, ... - колбась побочные эффекты где вздумается.
zim 09.07.2012 12:16 # 0
roman-kashitsyn 09.07.2012 13:24 # +4
Java, к примеру, поддерживает и форсирует ООП-стиль, но не является чистым ООП-языком, ибо примитивы. Тем не менее, Java называют объектно-ориентированным языком. Аналогичная ситуация с "функциональными" языками, что вызывает много недоразумений.
Не критики ради, просто решил заострить внимание на несовершенстве терминологии.
Lure Of Chaos 09.07.2012 12:35 # 0
это же и есть чистый код. или я что-то упускаю?
zim 09.07.2012 12:41 # 0
roman-kashitsyn 09.07.2012 12:06 # +3
PASCAL АНОМАЛЕН
Lure Of Chaos 09.07.2012 12:36 # +2
sayidandrtfm 09.07.2012 13:20 # +1
wvxvw 09.07.2012 15:04 # 0
bormand 09.07.2012 11:04 # 0
Kirinyale 09.07.2012 11:39 # +9
Fai 09.07.2012 13:25 # +2
bormand 09.07.2012 14:32 # +1
Компилятор: а вот тут в строке 15, возможно вы имели в виду...
Программист: Какой нах ворнинг?? Скомпилируй и заткнись!
[-Werror]
Компилятор: Что за нах ты написал в 15й строке!? Заткнись и иди перепиливать.
Программист: okay...
defecate-plusplus 09.07.2012 14:40 # 0
[/W4]
Компилятор: а вот тут в строке 16, мне кажется немного подозрительным...
Программист: да всё ок, тебе показалось, закоммичу на /W3 и пойду пить пиво
Тарас: КРЕСТОБЛЯДСКИЙ КРЕСТОКОМПИЛЯТОР!!!
bormand 09.07.2012 14:42 # +9
[В любой ситуации]
Тарас: КРЕСТОБЛЯДСКИЙ КРЕСТОКОМПИЛЯТОР!!!
Fai 09.07.2012 14:57 # 0
TarasB 09.07.2012 15:18 # +1
[/W4]
Я: вот на этой вот строчке компилятор выводит такое вод предупреждение, мне пришлось написать вот такой костыль, чтобы его не было, а как правильно?
Крестобляди: Ты чё, дурак что ли, warn off написать не можешь?
Самый умный крестовик: Ну попробуй добавить вот такую строчку, чтобы указать компилятору, что ты в курсе и учти, что тебе придётся не делать некоторые другие вещи.
Адеры: Допиши эту прагму, тогда ты сможешь делать то, что тебе надо, но будет запрещено делать некоторые другие вещи, на которые это предупреждение косвенно намекает.
interested 09.07.2012 15:34 # +3
TarasB 09.07.2012 15:35 # +2
defecate-plusplus 09.07.2012 15:38 # −1
rat4 09.07.2012 15:47 # 0
TarasB 09.07.2012 16:37 # 0
Fai 09.07.2012 16:30 # +1
Варнинги указывают, что код возможно плохой.
Если варнинг указывает на хороший код - виноват анализатор.
Если варнинг указывает на плохой код - виноват программист.
Но самое главное, что нужно не извращаться, а писать короткий, понятный и ясный код, который прост в сопровождении. В таком коде варнингов не будет.
А все эти while (100500 операторов для "эффективности") <пусто>; - извращения.
Эффективность добавляют в конце и не за счёт пары тактов, а за счёт замены алгоритма со сложностью O( n^2 ) на O( log n ).
roman-kashitsyn 09.07.2012 16:34 # +1
Это не извращения, это C-style :)
Fai 09.07.2012 16:41 # +1
guest 12.07.2012 23:33 # +2
bormand 09.07.2012 19:03 # +1
sayidandrtfm 09.07.2012 21:38 # −1
Не говори никому. Не надо.
roman-kashitsyn 09.07.2012 23:43 # 0
(c) "The C Programming Language"
Fai 10.07.2012 09:35 # +2
absolut 10.07.2012 11:35 # 0
TarasB 10.07.2012 12:06 # +3
sayidandrtfm 10.07.2012 10:01 # 0
Гражданин Fai — любитель(средняя весовая) вбросить.
А вот внезапно закрыть срачь(тот самый случай когда троллят троллей), можно
было немного тоньше. Ну да ладно.
Fai 10.07.2012 10:55 # 0
3.14159265 10.07.2012 13:24 # 0