How to resolve the algorithm Bernoulli numbers step by step in the Haskell programming language
How to resolve the algorithm Bernoulli numbers step by step in the Haskell programming language
Table of Contents
Problem Statement
Bernoulli numbers are used in some series expansions of several functions (trigonometric, hyperbolic, gamma, etc.), and are extremely important in number theory and analysis. Note that there are two definitions of Bernoulli numbers; this task will be using the modern usage (as per The National Institute of Standards and Technology convention). The nth Bernoulli number is expressed as Bn.
The Akiyama–Tanigawa algorithm for the "second Bernoulli numbers" as taken from wikipedia is as follows:
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Bernoulli numbers step by step in the Haskell programming language
This Haskell code generates and prints the Bernoulli numbers up to a specified index (60 by default). Bernoulli numbers are a sequence of rational numbers that occur naturally in many mathematical contexts.
Here's a breakdown of the code:
-
Importing Modules:
import Data.Ratio import System.Environment
These modules provide functions for working with rational numbers and for interacting with the command line.
-
main
Function:main = getArgs >>= printM . defaultArg where defaultArg as = if null as then 60 else read (head as)
The
main
function is the entry point of the program. It uses thegetArgs
function to retrieve command-line arguments. If no arguments are provided, it defaults to generating the first 60 Bernoulli numbers. If arguments are provided, it reads the first argument as an integer and uses that as the upper bound for generating the numbers. -
printM
Function:printM m = mapM_ (putStrLn . printP) . takeWhile ((<= m) . fst) . filter (\(_, b) -> b /= 0 % 1) . zip [0 ..] $ bernoullis
The
printM
function takes a rational numberm
and prints the Bernoulli numbers up to that index. It applies theprintP
function to each Bernoulli number and usesmapM_
to print them one by one. -
printP
Function:printP (i, r) = "B(" ++ show i ++ ") = " ++ show (numerator r) ++ "/" ++ show (denominator r)
The
printP
function takes a pair of a numberi
and a rational numberr
and prints it in a user-friendly format. It displays the Bernoulli numberB(i)
as a fraction with numerator and denominator. -
bernoullis
Function:bernoullis = map head . iterate (ulli 1) . map berno $ enumFrom 0 where berno i = 1 % (i + 1) ulli _ [_] = [] ulli i (x:y:xs) = (i % 1) * (x - y) : ulli (i + 1) (y : xs)
The
bernoullis
function generates the Bernoulli numbers using a recursive approach. It starts with the initial Bernoulli numberB(0) = 1
and then calculates subsequent numbers using a recurrence relation. Theberno
function provides the initial Bernoulli numbers, and theulli
function calculates the differences between consecutive Bernoulli numbers. -
Improved Bernoulli Number Generation (with
faulhaber
):This version of the code provides an alternative method for generating Bernoulli numbers using the Faulhaber triangle. It defines the
bernouillis
function as follows:bernouillis :: Integer -> [Rational] bernouillis = fmap head . tail . scanl faulhaber [] . enumFromTo 0
The
faulhaber
function constructs the Faulhaber triangle and uses it to generate Bernoulli numbers. It iteratively calculates the differences between consecutive rows of the triangle. -
faulhaber
Function:faulhaber :: [Ratio Integer] -> Integer -> [Ratio Integer] faulhaber rs n = (:) =<< (-) 1 . sum $ zipWith ((*) . (n %)) [2 ..] rs
The
faulhaber
function takes a list of rational numbersrs
and an integern
and generates the next row of the Faulhaber triangle. It multiplies each element ofrs
byn %
and subtracts the sum from 1. -
Testing and Formatting:
The code includes a
main
function for testing and formatting the output. It generates the first 60 Bernoulli numbers, calculates their numerators' lengths, and prints the results in a table format.The
fTable
function is used for formatting the table, whileshowRatio
andrjust
are helper functions for displaying rational numbers and right-justifying strings.
Overall, this code demonstrates two different approaches for generating Bernoulli numbers in Haskell and provides a user-friendly interface for viewing the results.
Source code in the haskell programming language
import Data.Ratio
import System.Environment
main = getArgs >>= printM . defaultArg
where
defaultArg as =
if null as
then 60
else read (head as)
printM m =
mapM_ (putStrLn . printP) .
takeWhile ((<= m) . fst) . filter (\(_, b) -> b /= 0 % 1) . zip [0 ..] $
bernoullis
printP (i, r) =
"B(" ++ show i ++ ") = " ++ show (numerator r) ++ "/" ++ show (denominator r)
bernoullis = map head . iterate (ulli 1) . map berno $ enumFrom 0
where
berno i = 1 % (i + 1)
ulli _ [_] = []
ulli i (x:y:xs) = (i % 1) * (x - y) : ulli (i + 1) (y : xs)
import Data.Bool (bool)
import Data.Ratio (Ratio, denominator, numerator, (%))
-------------------- BERNOULLI NUMBERS -------------------
bernouillis :: Integer -> [Rational]
bernouillis =
fmap head
. tail
. scanl faulhaber []
. enumFromTo 0
faulhaber :: [Ratio Integer] -> Integer -> [Ratio Integer]
faulhaber rs n =
(:) =<< (-) 1 . sum $
zipWith ((*) . (n %)) [2 ..] rs
--------------------------- TEST -------------------------
main :: IO ()
main = do
let xs = bernouillis 60
w = length $ show (numerator (last xs))
putStrLn $
fTable
"Bernouillis from Faulhaber triangle:\n"
(show . fst)
(showRatio w . snd)
id
(filter ((0 /=) . snd) $ zip [0 ..] xs)
------------------------ FORMATTING ----------------------
fTable ::
String ->
(a -> String) ->
(b -> String) ->
(a -> b) ->
[a] ->
String
fTable s xShow fxShow f xs =
let w = maximum (length . xShow <$> xs)
in unlines $
s :
fmap
( ((<>) . rjust w ' ' . xShow)
<*> ((" -> " <>) . fxShow . f)
)
xs
showRatio :: Int -> Rational -> String
showRatio w r =
let d = denominator r
in rjust w ' ' $ show (numerator r)
<> bool [] (" / " <> show d) (1 /= d)
rjust :: Int -> a -> [a] -> [a]
rjust n c = drop . length <*> (replicate n c <>)
You may also check:How to resolve the algorithm File size step by step in the Pike programming language
You may also check:How to resolve the algorithm 15 puzzle solver step by step in the Phix programming language
You may also check:How to resolve the algorithm Old lady swallowed a fly step by step in the Perl programming language
You may also check:How to resolve the algorithm Text processing/Max licenses in use step by step in the jq programming language
You may also check:How to resolve the algorithm Additive primes step by step in the Lambdatalk programming language