Bernoulli numbers: Difference between revisions
m
→{{header|AppleScript}}: Tidy-up, more comments, minor optimisations.
(Added AppleScript.) |
m (→{{header|AppleScript}}: Tidy-up, more comments, minor optimisations.) |
||
Line 222:
=={{header|AppleScript}}==
<lang applescript>on bernoullis(n) -- Return a list of "numerator / denominator" texts representing Bernoulli numbers B(0) to B(n).
set listMathScript to getListMathScript(10) -- Script object providing custom list math routines.
Line 228:
set output to {}
-- Akiyama–Tanigawa algorithm for the "second Bernoulli numbers".
-- List 'a' will contain {numerator, denominator} lists
-- The numerators and denominators will in turn be lists containing integers
set a to {}
repeat with m from 0 to n
Line 236:
set a's end to result
repeat with j from m to 1 by -1
-- Retrieve the preceding
set {numerator1, denominator1} to a's item j
tell listMathScript
--
set lcd to its lcm(denominator1, denominator2)
set numerator1 to its multiply(numerator1, its |div|(lcd, denominator1))
set numerator2 to its multiply(numerator2, its |div|(lcd, denominator2))
-- Subtract numerator2 from numerator1 and multiply the result by j.
-- Assign the results to numerator2 and denominator2 for the next iteration.
set numerator2 to its multiply(its subtract(numerator1, numerator2), its intToList(j))
set denominator2 to lcd
end tell
--
set a's item j to {numerator2, denominator2}
end repeat
-- The fraction just stored in a's first slot is Bernoulli(m). Reduce it and append a text representation to the output.
tell listMathScript
set gcd to its hcf(numerator2, denominator2)
Line 266 ⟶ 265:
on getListMathScript(base)
script
on multiply(
set
set
set productLength to
set product to {}
repeat productLength times
Line 275 ⟶ 274:
end repeat
-- Long multiplication algorithm, updating product digits on the fly instead of summing rows at the end.
repeat with lst2Index from
set carry to 0
set productIndex to
repeat with
set product's item productIndex to (
set carry to
set productIndex to productIndex - 1
end repeat
Line 298 ⟶ 299:
end multiply
on subtract(
set
set
copy
repeat (
set
end repeat
repeat (lst1Length - lst2Length)
set lst2's beginning to 0
end repeat
repeat with i from
set
set
if ((lst2Greater) or (lst1Digit > lst2Digit)) then exit repeat
end repeat
-- If so, set up to subtract lst1 from lst2 instead. We'll invert the result's sign at the end.
set lst2 to lst1
set lst1 to it
end tell▼
repeat with i from
set difference's beginning to (it mod base)
set borrow to 1 - (it div base)
end tell
end repeat
if (
▲ if (|b > a|) then invert(difference)
return difference
end subtract
on |div|(
return divide(
end |div|
on |mod|(
return divide(
end |mod|
on divide(
set dividend to trim(
set divisor to trim(
set dividendLength to (count dividend)
set divisorLength to (count divisor)
if (divisorLength > dividendLength) then return {quotient:{0}, remainder:
-- Note the dividend's and divisor's signs, but use absolute values in the division.
set dividendNegative to (dividend's beginning < 0)
if (dividendNegative) then invert(dividend)
Line 350 ⟶ 359:
if (divisorNegative) then invert(divisor)
-- Long-division algorithm, but quotient digits are subtraction counts.
set quotient to {}
if (divisorLength
set
else
set
end if
repeat with nextSlot from divisorLength to dividendLength
set remainder's end
▲ set q to q + 1
▲ set segment to newSegment
end repeat
set end of quotient to
end repeat
-- The quotient's negative if the input signs are different.
if (dividendNegative ≠ divisorNegative) then invert(quotient)
-- The remainder
if (dividendNegative) then invert(
return {quotient:quotient, remainder:
end divide
on lcm(
return multiply(
end lcm
on hcf(
set
set
repeat until (
set x to
set
set
end repeat
if (
return
end hcf
Line 398 ⟶ 406:
end invert
on trim(lst) -- Return a copy of
repeat with i from 1 to (count lst)
if (lst's item i is not 0) then exit repeat
Line 444 ⟶ 452:
set output to {""}
set padding to " = "
set bernoulliNumbers to bernoullis(maxN)
repeat with n from 0 to maxN
set bernie to bernoulliNumbers's item (n + 1)
|