Лучший алгоритм для оценки математического выражения?

Внесите следующие изменения в свой класс адаптера и проверьте один раз

@Override
public int getCount() {
    //return 0;
    return songs.size();
}
13
задан Steve 21 February 2009 в 10:54
поделиться

2 ответа

Если Вы хотите сделать это с Delphi, Вы могли бы изучить как JclExprEval работы единицы, часть Библиотеки Кода ДЖЕДАЯ. Я записал это несколько лет назад (это немного сверхспроектировано); это анализирует функции и переменные и может вручить Вам назад указатель метода, который оценивает выражение быстро. Передайте переменные в ссылкой, и можно изменить их непосредственно, и переоцененное выражение будет вычислено соответственно.

В любом случае основы того, как это работает, могут быть полезными для Вас. Синтаксический анализ методом рекурсивного спуска выражений легок, и путем создания дерева, которое можно оценить многократно без перепарсинга. JclExprEval на самом деле генерирует код для простой стековой машины, так, чтобы он мог работать немного быстрее, чем древовидная интерпретация; стековые машины в основном ограничивают свои операции памяти массивами и используют переключатели для кодов операций, в то время как древовидная интерпретация переходит по ссылкам всюду по "куче" и часто использует виртуальную отправку (или двойную отправку) для кодов операций, таким образом, они обычно заканчивают медленнее.

Проявление того же подхода как JclExprEval в парсинге, но записанный в C# и создании Expression, как Marc предлагает, другой совершенно допустимый подход. Скомпилированное в JIT выражение должно быть вполне немного быстрее, чем интерпретируемая программа выражения или дерево, которые самостоятельно намного быстрее, чем парсинг.

15
ответ дан 1 December 2019 в 22:08
поделиться

В C# с.NET 3.5, можно использовать Expression для этого; можно создать параметризованное выражение и затем скомпилировать его в делегата. Это точно, что я сделал для аспекта математики Finguistics. У меня все еще есть код парсинга, который я использовал, если Вы хотите его...

Основной прием, который я использовал, был то, что для хранения типа делегата известным я использовал массив в качестве входного типа - обработка другого args как прибытие [0], arr1, прибытие [2] и т.д. Это означает, что я мог скомпилировать в (например), a Func<decimal[], decimal> (берет массив decimals, a возвратов decimal).

После того как Вы звонили Compile(), это симпатично как, хотя у Вас был код, чтобы сделать это непосредственно.

(редактирование)

Как краткий пример использования Expression таким образом (с трудно кодированной функцией), посмотрите ниже. Синтаксический анализатор я уже в настоящее время писал работы как средство проверки предиката - т.е. проверять это"? + (2 *?-?) = 22 +?" - но не было бы трудно изменить его для возврата результата вместо этого (и представлять больше операций, как sin/pow/ и т.д. - по-видимому, путем отображения их непосредственно на открытые методы для объекта помощника (через Expression.Call)).

using System;
using System.Linq.Expressions;
static class Program
{
    static void Main()
    {
        var args = Expression.Parameter(typeof(float[]), "args");
        var x = Expression.ArrayIndex(args, Expression.Constant(0));
        var y = Expression.ArrayIndex(args, Expression.Constant(1));
        var add = Expression.Add(x, y);
        var lambda = Expression.Lambda<Func<float[], float>>(add, args);

        Func<float[], float> func = lambda.Compile();
        Console.WriteLine(func.Call(1, 2));
        Console.WriteLine(func.Call(3, 4));
        Console.WriteLine(func.Call(5, 6));
    }

    static T Call<T>(this Func<T[], T> func, params T[] args)
    { // just allows "params" usage...
        return func(args);
    } 
}
8
ответ дан 1 December 2019 в 22:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: