Haskell function to error-diffuse a floating value to a list of integers
up vote
3
down vote
favorite
I needed to write a function which would 'error diffuse' floating values to integers:
errorDiffuse :: Double -> Int -> Double -> [Int]
errorDiffuse _ 0 _ =
errorDiffuse v num err = tv : errorDiffuse v (num - 1) (err + v - fromIntegral tv)
where tv = truncate (v + err)
So that, for example:
errorDiffuse 1.4 10 0 => [1,1,2,1,1,2,1,2,1,1]
(i.e., the function produces a list of num
integers, each of which is the ceiling or floor of v
, starting with a given error value (zero in this case)).
Is there a better way to write this sort of for
loop? What's the higher-order function I ought to be thinking in terms of?
haskell
add a comment |
up vote
3
down vote
favorite
I needed to write a function which would 'error diffuse' floating values to integers:
errorDiffuse :: Double -> Int -> Double -> [Int]
errorDiffuse _ 0 _ =
errorDiffuse v num err = tv : errorDiffuse v (num - 1) (err + v - fromIntegral tv)
where tv = truncate (v + err)
So that, for example:
errorDiffuse 1.4 10 0 => [1,1,2,1,1,2,1,2,1,1]
(i.e., the function produces a list of num
integers, each of which is the ceiling or floor of v
, starting with a given error value (zero in this case)).
Is there a better way to write this sort of for
loop? What's the higher-order function I ought to be thinking in terms of?
haskell
add a comment |
up vote
3
down vote
favorite
up vote
3
down vote
favorite
I needed to write a function which would 'error diffuse' floating values to integers:
errorDiffuse :: Double -> Int -> Double -> [Int]
errorDiffuse _ 0 _ =
errorDiffuse v num err = tv : errorDiffuse v (num - 1) (err + v - fromIntegral tv)
where tv = truncate (v + err)
So that, for example:
errorDiffuse 1.4 10 0 => [1,1,2,1,1,2,1,2,1,1]
(i.e., the function produces a list of num
integers, each of which is the ceiling or floor of v
, starting with a given error value (zero in this case)).
Is there a better way to write this sort of for
loop? What's the higher-order function I ought to be thinking in terms of?
haskell
I needed to write a function which would 'error diffuse' floating values to integers:
errorDiffuse :: Double -> Int -> Double -> [Int]
errorDiffuse _ 0 _ =
errorDiffuse v num err = tv : errorDiffuse v (num - 1) (err + v - fromIntegral tv)
where tv = truncate (v + err)
So that, for example:
errorDiffuse 1.4 10 0 => [1,1,2,1,1,2,1,2,1,1]
(i.e., the function produces a list of num
integers, each of which is the ceiling or floor of v
, starting with a given error value (zero in this case)).
Is there a better way to write this sort of for
loop? What's the higher-order function I ought to be thinking in terms of?
haskell
haskell
edited Nov 19 at 20:43
200_success
127k15148411
127k15148411
asked Nov 2 '11 at 14:12
stusmith
17517
17517
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
3
down vote
accepted
First I'd get rid of the dependency on num
, since that's just a counter,
and you can use take num
on an infinite list of errorDiffuses
:
errorDiffuses :: Double -> Double -> [Int]
errorDiffuses v err = tv : errorDiffuses v (err + v - fromIntegral tv)
where
tv = truncate (v + err)
So we have:
errorDiffuse' :: Double -> Int -> Double -> [Int]
errorDiffuse' v num err = take num $ errorDiffuses v err
Then I'd think about generating the list of errorDiffuses
differently.
Since we're trying to generate a list, that makes me think of unfolds
,
which you can find in Data.List:
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
The unfold takes a function that, given a seed, produces the next
value in the outputted list, along with a new seed. The function
starts with an intitial seed, and keeps using those seeds, adding to the
list until the function returns Nothing
.
The function we're looking for is the following:
nextErrorDiffuse :: Double -> Double -> Maybe (Int, Double)
nextErrorDiffuse v err = Just (tv, err + v - fromIntegral tv)
where
tv = truncate (v + err)
Our list is infinite, so we always return a Just
value. The value that is output at each stage is tv
, and the next "seed" is given by err + v - fromIntegral tv
.
Putting things together we have:
errorDiffuse'' :: Double -> Int -> Double -> [Int]
errorDiffuse'' v num err = take num $ unfoldr (nextErrorDiffuse v) err
Fantastic, thankyou! I don't thinkunfoldr
is in my mental toolkit yet but it was exactly the sort of thing I was thinking of.
– stusmith
Nov 2 '11 at 16:34
Glad I could help :-)
– Nicolas Wu
Nov 2 '11 at 16:37
unfoldr
is a great tool to add to your toolkit. Whenever you need to produce a list from some seed value(s),unfoldr
should come to mind.
– Dan Burton
Nov 26 '11 at 20:03
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
accepted
First I'd get rid of the dependency on num
, since that's just a counter,
and you can use take num
on an infinite list of errorDiffuses
:
errorDiffuses :: Double -> Double -> [Int]
errorDiffuses v err = tv : errorDiffuses v (err + v - fromIntegral tv)
where
tv = truncate (v + err)
So we have:
errorDiffuse' :: Double -> Int -> Double -> [Int]
errorDiffuse' v num err = take num $ errorDiffuses v err
Then I'd think about generating the list of errorDiffuses
differently.
Since we're trying to generate a list, that makes me think of unfolds
,
which you can find in Data.List:
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
The unfold takes a function that, given a seed, produces the next
value in the outputted list, along with a new seed. The function
starts with an intitial seed, and keeps using those seeds, adding to the
list until the function returns Nothing
.
The function we're looking for is the following:
nextErrorDiffuse :: Double -> Double -> Maybe (Int, Double)
nextErrorDiffuse v err = Just (tv, err + v - fromIntegral tv)
where
tv = truncate (v + err)
Our list is infinite, so we always return a Just
value. The value that is output at each stage is tv
, and the next "seed" is given by err + v - fromIntegral tv
.
Putting things together we have:
errorDiffuse'' :: Double -> Int -> Double -> [Int]
errorDiffuse'' v num err = take num $ unfoldr (nextErrorDiffuse v) err
Fantastic, thankyou! I don't thinkunfoldr
is in my mental toolkit yet but it was exactly the sort of thing I was thinking of.
– stusmith
Nov 2 '11 at 16:34
Glad I could help :-)
– Nicolas Wu
Nov 2 '11 at 16:37
unfoldr
is a great tool to add to your toolkit. Whenever you need to produce a list from some seed value(s),unfoldr
should come to mind.
– Dan Burton
Nov 26 '11 at 20:03
add a comment |
up vote
3
down vote
accepted
First I'd get rid of the dependency on num
, since that's just a counter,
and you can use take num
on an infinite list of errorDiffuses
:
errorDiffuses :: Double -> Double -> [Int]
errorDiffuses v err = tv : errorDiffuses v (err + v - fromIntegral tv)
where
tv = truncate (v + err)
So we have:
errorDiffuse' :: Double -> Int -> Double -> [Int]
errorDiffuse' v num err = take num $ errorDiffuses v err
Then I'd think about generating the list of errorDiffuses
differently.
Since we're trying to generate a list, that makes me think of unfolds
,
which you can find in Data.List:
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
The unfold takes a function that, given a seed, produces the next
value in the outputted list, along with a new seed. The function
starts with an intitial seed, and keeps using those seeds, adding to the
list until the function returns Nothing
.
The function we're looking for is the following:
nextErrorDiffuse :: Double -> Double -> Maybe (Int, Double)
nextErrorDiffuse v err = Just (tv, err + v - fromIntegral tv)
where
tv = truncate (v + err)
Our list is infinite, so we always return a Just
value. The value that is output at each stage is tv
, and the next "seed" is given by err + v - fromIntegral tv
.
Putting things together we have:
errorDiffuse'' :: Double -> Int -> Double -> [Int]
errorDiffuse'' v num err = take num $ unfoldr (nextErrorDiffuse v) err
Fantastic, thankyou! I don't thinkunfoldr
is in my mental toolkit yet but it was exactly the sort of thing I was thinking of.
– stusmith
Nov 2 '11 at 16:34
Glad I could help :-)
– Nicolas Wu
Nov 2 '11 at 16:37
unfoldr
is a great tool to add to your toolkit. Whenever you need to produce a list from some seed value(s),unfoldr
should come to mind.
– Dan Burton
Nov 26 '11 at 20:03
add a comment |
up vote
3
down vote
accepted
up vote
3
down vote
accepted
First I'd get rid of the dependency on num
, since that's just a counter,
and you can use take num
on an infinite list of errorDiffuses
:
errorDiffuses :: Double -> Double -> [Int]
errorDiffuses v err = tv : errorDiffuses v (err + v - fromIntegral tv)
where
tv = truncate (v + err)
So we have:
errorDiffuse' :: Double -> Int -> Double -> [Int]
errorDiffuse' v num err = take num $ errorDiffuses v err
Then I'd think about generating the list of errorDiffuses
differently.
Since we're trying to generate a list, that makes me think of unfolds
,
which you can find in Data.List:
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
The unfold takes a function that, given a seed, produces the next
value in the outputted list, along with a new seed. The function
starts with an intitial seed, and keeps using those seeds, adding to the
list until the function returns Nothing
.
The function we're looking for is the following:
nextErrorDiffuse :: Double -> Double -> Maybe (Int, Double)
nextErrorDiffuse v err = Just (tv, err + v - fromIntegral tv)
where
tv = truncate (v + err)
Our list is infinite, so we always return a Just
value. The value that is output at each stage is tv
, and the next "seed" is given by err + v - fromIntegral tv
.
Putting things together we have:
errorDiffuse'' :: Double -> Int -> Double -> [Int]
errorDiffuse'' v num err = take num $ unfoldr (nextErrorDiffuse v) err
First I'd get rid of the dependency on num
, since that's just a counter,
and you can use take num
on an infinite list of errorDiffuses
:
errorDiffuses :: Double -> Double -> [Int]
errorDiffuses v err = tv : errorDiffuses v (err + v - fromIntegral tv)
where
tv = truncate (v + err)
So we have:
errorDiffuse' :: Double -> Int -> Double -> [Int]
errorDiffuse' v num err = take num $ errorDiffuses v err
Then I'd think about generating the list of errorDiffuses
differently.
Since we're trying to generate a list, that makes me think of unfolds
,
which you can find in Data.List:
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
The unfold takes a function that, given a seed, produces the next
value in the outputted list, along with a new seed. The function
starts with an intitial seed, and keeps using those seeds, adding to the
list until the function returns Nothing
.
The function we're looking for is the following:
nextErrorDiffuse :: Double -> Double -> Maybe (Int, Double)
nextErrorDiffuse v err = Just (tv, err + v - fromIntegral tv)
where
tv = truncate (v + err)
Our list is infinite, so we always return a Just
value. The value that is output at each stage is tv
, and the next "seed" is given by err + v - fromIntegral tv
.
Putting things together we have:
errorDiffuse'' :: Double -> Int -> Double -> [Int]
errorDiffuse'' v num err = take num $ unfoldr (nextErrorDiffuse v) err
answered Nov 2 '11 at 15:45
Nicolas Wu
21112
21112
Fantastic, thankyou! I don't thinkunfoldr
is in my mental toolkit yet but it was exactly the sort of thing I was thinking of.
– stusmith
Nov 2 '11 at 16:34
Glad I could help :-)
– Nicolas Wu
Nov 2 '11 at 16:37
unfoldr
is a great tool to add to your toolkit. Whenever you need to produce a list from some seed value(s),unfoldr
should come to mind.
– Dan Burton
Nov 26 '11 at 20:03
add a comment |
Fantastic, thankyou! I don't thinkunfoldr
is in my mental toolkit yet but it was exactly the sort of thing I was thinking of.
– stusmith
Nov 2 '11 at 16:34
Glad I could help :-)
– Nicolas Wu
Nov 2 '11 at 16:37
unfoldr
is a great tool to add to your toolkit. Whenever you need to produce a list from some seed value(s),unfoldr
should come to mind.
– Dan Burton
Nov 26 '11 at 20:03
Fantastic, thankyou! I don't think
unfoldr
is in my mental toolkit yet but it was exactly the sort of thing I was thinking of.– stusmith
Nov 2 '11 at 16:34
Fantastic, thankyou! I don't think
unfoldr
is in my mental toolkit yet but it was exactly the sort of thing I was thinking of.– stusmith
Nov 2 '11 at 16:34
Glad I could help :-)
– Nicolas Wu
Nov 2 '11 at 16:37
Glad I could help :-)
– Nicolas Wu
Nov 2 '11 at 16:37
unfoldr
is a great tool to add to your toolkit. Whenever you need to produce a list from some seed value(s), unfoldr
should come to mind.– Dan Burton
Nov 26 '11 at 20:03
unfoldr
is a great tool to add to your toolkit. Whenever you need to produce a list from some seed value(s), unfoldr
should come to mind.– Dan Burton
Nov 26 '11 at 20:03
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f5757%2fhaskell-function-to-error-diffuse-a-floating-value-to-a-list-of-integers%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown