2014-12-12 2 views
0

У меня есть этот код, чтобы отработать сумму квадратов целых чисел в диапазоне от т: псуммы квадратов целых чисел Haskell

sumsquares :: Integral a=> Int -> Int -> Int -> Int 
sumsquares m n middle 
| m > n = error "First number cannot be bigger than second number" 
|m==n = m*m 
|otherwise = m*m + sumsquares (m+1)n 

Как бы я переопределить функцию sumsquares для этой цели?

Если в диапазоне m: n находится более одного числа, вычислите середину диапазона и добавьте сумму квадратов (m: средняя) к сумме квадратов (средний + 1: n), , в противном случае существует только одно число в диапазоне m: n, поэтому m = = n, а решение - только квадрат m. (Обратите внимание, что при таком подходе рекурсия объединяет два полурешения: каждая подзадача примерно вдвое меньше общей проблемы).

+0

Я не понимаю, для чего вам нужен средний ... Вы не используете его, и из вашего описания того, как я думаю, вы хотите его использовать, ничего не спасает. – jamshidh

+0

Возможный дубликат [Сумма квадратов с использованием Haskell] (http://stackoverflow.com/questions/27407773/sum-of-squares-using-haskell) – Jubobs

+0

Я думаю, это не дубликат, так как вопрос требует другого решения состав. –

ответ

3

В вашей первоначальной функции ограничение класса Integral a в сигнатуре типа устарело (a не упоминается нигде в подписи, не так ли?). Кроме того, третий параметр функции (middle) остается неиспользованным. Таким образом, вы могли бы написать как

sumsquares :: Int -> Int -> Int 
sumsquares m n 
    | m > n  = error "First number cannot be bigger than second number" 
    | m == n = m * m 
    | otherwise = m * m + sumsquares (m + 1) n 

Переписывая его, чтобы перейти от decrease-and-conquer схемы строгой схемы разделяй и властвуй, то просто включает в себя адаптацию рекурсивный случай соответственно:

sumsquares :: Int -> Int -> Int 
sumsquares m n 
    | m > n  = error "First number cannot be bigger than second number" 
    | m == n = m * m 
    | otherwise = let middle = (m + n) `div` 2 
       in sumsquares m middle + sumsquares (middle + 1) n 

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

+0

ahhh, я вижу, что вы имеете в виду, как бы я использовал след, чтобы показать его вычисления? – Harry

+1

@Harry: используйте 'Debug.Trace'; см. http://lpaste.net/116298. –

+0

@ Списки Harry, однако, сильно распараллеливаются, поэтому вы получите только что-то от этого, если каждый расчет дорог. Это не так, поэтому самый быстрый способ суммировать квадраты элементов списка - это просто сделать это по порядку, один за другим. – dfeuer