let rec run f x n =
match n with
| t when t <= 0 -> ()
| _ -> f x
run f x (n-1)
иlet rec run f x n =
match n with
| t when t <= 0 -> ()
| _ -> f x
run f x (n-1)
Разные вещи. Еще с ";" не все ясно. Так что вопросов море.Также хочу сказать, что не собираюсь пытаться писать для обучения языку. Здесь скорее всего будут какие-то наработки или интересные моменты.
Ну и первое, что рассмотрим на F# - нахождение производных. Собственно сама формула выглядит так:
let d (f : float->float) sigma x =
let dx = sqrt sigma
(f (x+dx) - f (x-dx)) / (2.0*dx);
Думаю тут все ясно. Хочется только показать красивый способ задания самой функции производной:let f' x = d f sigma x;
Теперь производную можно найти в любой точке таким образом: f' x или кому проще - f'(x).Для тестирования возьмем такую функцию:
let f1 x = x ** 3.0 - x - 1.0
let f2 x = x*x*x - x - 1.0
Здесь появляется оператор **, который возводит в степень. Конечно удобная вещь, давно мечтал, но мы еще его вспомним.Для точности проведем 5 млн. измерений. Для этого воспользуемся как вышеуказанной функцией run, так и такой модификацией:
let rec run2 f x n =
for i=0 to n-1 do
f x
Кстати, не претендую на очень качественные тесты, так что топтать нет смысла, но если предложите вариант, да еще не сильно усложняющий код - буду рад. Так вот замер времени будет производится следующим образом:let time f =
let timer = System.Diagnostics.Stopwatch.StartNew ()
f ()
let t = timer.Elapsed
printfn "Time taken = %O" t
Ну и собственно все, дальше делаем всевозможные комбинации и получаем 4 варианта:
let f'1 x = d (fun x -> x ** 3.0 - x - 1.0) sigma x |> ignore
let f'2 x = d (fun x -> x*x*x - x - 1.0) sigma x |> ignore
let f'3 x = d f1 sigma x |> ignore
let f'4 x = d f2 sigma x |> ignore
ignore - для указания, что функция возвращает unit.Ну и еще для разных run и run2. получим так:
printfn "With recursion:"
time (fun q -> run f'1 t N)
time (fun q -> run f'2 t N)
time (fun q -> run f'3 t N)
time (fun q -> run f'4 t N)
printfn "With 'for' operator:"
time (fun q -> run2 f'1 t N)
time (fun q -> run2 f'2 t N)
time (fun q -> run2 f'3 t N)
time (fun q -> run2 f'4 t N)
Так же, для сравнения, сделаем похожие вещи на C# и Matlab (если кого заинтересует, могу выложить и их код). Ну и собственно результаты измерений (в секундах):
matlab - 63.7067
C# - 0.4072
C# - 0.4320 (через делегат)
F# - рекурсия:
f'1 - 1.5936
f'2 - 0.4817
f'3 - 1.8626
f'4 - 0.6929
F# - цикл:
f'1 - 1.5817
f'2 - 0.4471
f'3 - 1.8588
f'4 - 0.7032
Ну что можно сказать, оператор ** довольно сильно тормозит, так что нужно следить, где его использовать. Также, я не ожидал что F# будет быстрее C#, так что результат меня вполне удовлетворил. А вот Matlab все-таки MATrix LABoratory, так что в ближайшее время посмотрю, кто из них быстрее списки перемножает :)
Комментариев нет:
Отправить комментарий