Кстати, вот один баг,
перекочевавший еще из самой первой версии Mathematica:
[no]In[1]:= f[Infinity] - f[Infinity]
Out[1]= 0
In[2]:= f[x_] = x;
f[Infinity] - f[Infinity]
During evaluation of In[2]:= \[Infinity]::indet: Indeterminate expression -\[Infinity]+\[Infinity] encountered. >>
Out[3]= Indeterminate[/no]
Очевидно, первый результат неверен.
Или вот еще один древнейший баг:
In[1]:= N[Sin[3141592653589793238]]
Out[1]= -0.64475
In[2]:= N[Sin[3141592653589793238], 6]
Out[2]= -0.446315
Здесь в обоих случаях берется синус
точной величины. Причем единственный способ узнать, чему же равен синус такой величины, - использовать N[], т.к.
In[3]:= Sin[3141592653589793238]
Out[3]= Sin[3141592653589793238]
Однако, как легко видеть, здесь-то мы и попадаем в ловушку: результат такого очевидного (и предписанного документацией) действия оказывается неверен, если мы не зададим значение Precision для результата! Глядя на такие чудеса, начинаешь думать: имеет ли вообще смысл использовать N[] без указания целевой точности? Результат никем не гарантирован...
Добавлено: r_green Цитата: Другими словами, достаточно сложный алгоритм в вынужден строить (хотя бы частично и неявно) аналитическое представление входной ф-ции, выполняя своего рода reverse engineering. Чего можно избежать, сразу дав ему ф-цию в виде выражения.
Для этого есть символьный Integrate[]. В практических задачах обычно никакой символьный анализ помочь не может - NIntegrate просто не должен совать нос не в свою область. Его задача - работать с функцией именно как с "черным ящиком". Редкие случаи (по сути, единичные классы задач), когда и правда возможно некоторое ускорение или увеличение точности за счет символьного анализа, должны быть частью символьной функции. Или уж, если на то пошло, этот дополнительный "мозг" должен быть легко отключаем без потерь, чего не наблюдается.
Ну да ладно с NIntegrate. А как насчет Plot[] (и всех остальных: ContourPlot[] и т.д.)? Как насчет FindMinimum[], да еще если однозначно указан метод, не требующий взятия производных, например "QuasiNewton" или "PrincipalAxis"? Зачем тут символьный анализ? Пользователь ожидает, что система будет действовать по известному алгоритму. Лишний "мозг" только вызывает недоумение и головную боль. В том, что поведение именно таково, нетрудно убедиться:
f[x_ /; Not@NumericQ[x]] := (Print["Symbolic evaluation"]; 2);
f[x_?NumericQ] := 1
Plot[f[x], {x, 1, 2}]
f[x_?NumericQ] := (Print["Numerical evaluation"]; 1)
Attributes[FindMinimum]
FindMinimum[f[x], {x, 0, 1}, Method -> "PrincipalAxis"]
FindMinimum[f[x], {x, 0, 1}, Method -> "QuasiNewton"]
(обратите внимание, что FindMinimum вообще не пытается изучить функцию численно, он уже все "знает". )
Цитата: мы как бы делаем ему оболочку, которую может "снять" только нужная нам ф-ция.
А почему бы не присвоить атрибут HoldRest тому же MatchQ[], чтобы не нужно было по любому поводу использовать HoldPattern? Да и вообще, зачем нужно "выполнять" выражения типа x_*x_ или, например, [no]Times[___, Power[___], ___][/no] (т.е. явно состоящие из паттернов)?
Вот пример реально возникшей у пользователя проблемы (False в первом случае) и несколько вариантов её решения:
[no]x = 2;
MatchQ[Times[-1, Power[s, -1]], Times[___, Power[___ /; x == 2], ___]]
MatchQ[Times[-1, Power[s, -1]],
HoldPattern@Times[___, Power[___ /; x == 2], ___]]
MatchQ[Times[-1, Power[s, -1]],
Unevaluated@Times[___, Power[___ /; x == 2], ___]]
Unprotect[MatchQ];
SetAttributes[MatchQ, HoldRest];
MatchQ[Times[-1, Power[s, -1]], Times[___, Power[___ /; x == 2], ___]]
(*проверка, что условие в паттерне работает*)
x = 3;
MatchQ[Times[-1, Power[s, -1]], Times[___, Power[___ /; x == 2], ___]]
Quit[][/no]