Harmonic series

From Rosetta Code
Revision as of 05:24, 27 May 2021 by Chunes (talk | contribs) (Add Factor)
Harmonic series is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
This page uses content from Wikipedia. The original article was at Harmonic number. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance)

In mathematics, the n-th harmonic number is the sum of the reciprocals of the first n natural numbers:

Hn = 1 + 1/2 + 1/3 + ... + 1/n

The series of harmonic numbers thus obtained is often loosely referred to as the harmonic series.

Harmonic numbers are closely related to the Riemann zeta function, and roughly approximate the natural logarithm function; differing by γ (lowercase Gamma), the Euler–Mascheroni constant.

The harmonic series is divergent, albeit quite slowly, and grows toward infinity.


Task
  • Write a function (routine, procedure, whatever it may be called in your language) to generate harmonic numbers.
  • Use that procedure to show the values of the first 20 harmonic numbers.
  • Find and show the position in the series of the first value greater than the integers 1 through 5


Stretch
  • Find and show the position in the series of the first value greater than the integers 6 through 10


Related


Factor

This solution uses the following (rather accurate) approximation of the harmonic numbers to find the first indices greater than the integers:

Hn ≈ ln(n) + γ + 1/2n - 1/12n2

where γ is the Euler-Mascheroni constant, approximately 0.5772156649.

Works with: Factor version 0.99 2021-02-05

<lang factor>USING: formatting grouping io kernel lists lists.lazy math math.functions math.ranges math.statistics math.text.english prettyprint sequences tools.memory.private ;

! Euler-Mascheroni constant CONSTANT: γ 0.5772156649

Hn-approx ( n -- ~Hn )
   [ log γ + 1 2 ] [ * /f + 1 ] [ sq 12 * /f - ] tri ;
lharmonics ( -- list ) 1 lfrom [ Hn-approx ] lmap-lazy ;
first-gt ( m -- n ) lharmonics swap '[ _ < ] lwhile llength ;

"First twenty harmonic numbers as mixed numbers:" print 100 [1,b] [ recip ] map cum-sum [ 20 head 5 group simple-table. nl ] [ "One hundredth:" print last . nl ] bi

"(zero based) Index of first value:" print 10 [1,b] [

   dup first-gt [ commas ] [ 1 + number>text ] bi
   "  greater than %2d: %6s (term number %s)\n" printf

] each</lang>

Output:
First twenty harmonic numbers as mixed numbers:
1               1+1/2              1+5/6             2+1/12              2+17/60
2+9/20          2+83/140           2+201/280         2+2089/2520         2+2341/2520
3+551/27720     3+2861/27720       3+64913/360360    3+90653/360360      3+114677/360360
3+274399/720720 3+5385503/12252240 3+2022061/4084080 3+42503239/77597520 3+9276623/15519504

One hundredth:
5+522561233577855727314756256041670736351/2788815009188499086581352357412492142272

(zero based) Index of first value:
  greater than  1:      1 (term number two)
  greater than  2:      3 (term number four)
  greater than  3:     10 (term number eleven)
  greater than  4:     30 (term number thirty-one)
  greater than  5:     82 (term number eighty-three)
  greater than  6:    226 (term number two hundred and twenty-seven)
  greater than  7:    615 (term number six hundred and sixteen)
  greater than  8:  1,673 (term number one thousand, six hundred and seventy-four)
  greater than  9:  4,549 (term number four thousand, five hundred and fifty)
  greater than 10: 12,366 (term number twelve thousand, three hundred and sixty-seven)

Phix

requires("0.8.4")
include mpfr.e
integer n = 1, gn = 1
mpq hn = mpq_init_set_si(1)
sequence gt = {}
puts(1,"First twenty harmonic numbers as rationals:\n")
while gn<=10 do
    if n<=20 then
        printf(1,"%18s%s",{mpq_get_str(hn),iff(mod(n,5)?" ","\n")})
    end if
    if n=100 then
        printf(1,"\nOne Hundredth:\n%s\n\n",{mpq_get_str(hn)})
    end if
    if mpq_cmp_si(hn,gn)>0 then
        gt &= n
        gn += 1
    end if
    n += 1
    mpq_add_si(hn,hn,1,n)
end while
printf(1,"(one based) Index of first value:\n")
for i=1 to length(gt) do
    printf(1,"  greater than %2d: %,6d (%s term)\n",{i,gt[i],ordinal(gt[i])})
end for
Output:
First twenty harmonic numbers as rationals:
                 1                3/2               11/6              25/12             137/60
             49/20            363/140            761/280          7129/2520          7381/2520
       83711/27720        86021/27720     1145993/360360     1171733/360360     1195757/360360
    2436559/720720  42142223/12252240   14274301/4084080 275295799/77597520  55835135/15519504

One Hundredth:
14466636279520351160221518043104131447711/2788815009188499086581352357412492142272

(one based) Index of first value:
  greater than  1:      2 (second term)
  greater than  2:      4 (fourth term)
  greater than  3:     11 (eleventh term)
  greater than  4:     31 (thirty-first term)
  greater than  5:     83 (eighty-third term)
  greater than  6:    227 (two hundred and twenty-seventh term)
  greater than  7:    616 (six hundred and sixteenth term)
  greater than  8:  1,674 (one thousand, six hundred and seventy-fourth term)
  greater than  9:  4,550 (four thousand, five hundred and fiftieth term)
  greater than 10: 12,367 (twelve thousand, three hundred and sixty-seventh term)

Raku

Using Lingua::EN::Numbers from the Raku ecosystem. <lang perl6>use Lingua::EN::Numbers;

my @H = [\+] (1..*).map: { FatRat.new( 1, $_ ) };

say "First twenty harmonic numbers as rationals:\n",

   @H[^20].&ratty.batch(5)».fmt("%18s").join: "\n";

put "\nOne Hundredth:\n", @H[99].&ratty;

say "\n(zero based) Index of first value:"; printf " greater than %2d: %6s (%s term)\n",

 $_, comma( my $i = @H.first(* > $_, :k) ), ordinal 1 + $i for 1..10;

sub ratty (*@a) { @a.map: { .narrow.^name eq 'Int' ?? .narrow !! .nude.join('/') } }</lang>

Output:
First twenty harmonic numbers as rationals:
                 1                3/2               11/6              25/12             137/60
             49/20            363/140            761/280          7129/2520          7381/2520
       83711/27720        86021/27720     1145993/360360     1171733/360360     1195757/360360
    2436559/720720  42142223/12252240   14274301/4084080 275295799/77597520  55835135/15519504

One Hundredth:
14466636279520351160221518043104131447711/2788815009188499086581352357412492142272

(zero based) Index of first value:
  greater than  1:      1 (second term)
  greater than  2:      3 (fourth term)
  greater than  3:     10 (eleventh term)
  greater than  4:     30 (thirty-first term)
  greater than  5:     82 (eighty-third term)
  greater than  6:    226 (two hundred twenty-seventh term)
  greater than  7:    615 (six hundred sixteenth term)
  greater than  8:  1,673 (one thousand, six hundred seventy-fourth term)
  greater than  9:  4,549 (four thousand, five hundred fiftieth term)
  greater than 10: 12,366 (twelve thousand, three hundred sixty-seventh term)