Natural logarithm

Introduction

edit

The natural logarithm of any real number   greater than zero is usually denoted by abbreviation  

For example, natural logarithm of   is:

# python code.
import decimal
dD = Decimal = decimal.Decimal
dgt = decimal.getcontext()
Precision = dgt.prec = 100
ln5 = Decimal(5).ln() ; ln5
Decimal('1.609437912434100374600759333226187639525601354268517721912647891474178987707657764630133878093179611')

The base of the system of natural logarithms is the number   which may be calculated as follows:

# python code.
e = Decimal(1).exp() ; e
e ** ln5 # e raised to power ln(5).
Decimal('2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427')
Decimal('5.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')

  raised to power  

When   we know from calculus that   and that  

Therefore  

Let   Then   is   taken   times.

Calculate  

pre = 200
Precision = dgt.prec = pre
lne = ( [ root for root in [e] for p in range (1,pre+1) for root in [root.sqrt()] ][-1] - 1 ) * (1 << pre) ; lne
'1.00000000000000000000000000000000000000000000000000000000000031115076389305708535720320268900621202935.....'

Number of accurate digits in result is about  

This calculation of   is accurate to   places of decimals, not bad for one line of simple python code using high-school math.

If all we want to do is calculate   we can stop here. However, this method contains many calculations of .sqrt(), very time consuming.

While simple and accurate, this method is slow.

This page presents a system for calculating   that is much faster than this simple method.

Generally, for   close to  

  where:

         


On this page there are two significant considerations that reduce time required to calculate  

  • For given value of   calculation of   is fast.
  • Value   is as small as possible so that calculation of   converges quickly.

Data Structures

edit

values_of_x0

edit
# python code.

import decimal
dD = Decimal = decimal.Decimal
dgt = decimal.getcontext()
Precision = dgt.prec = 100

length = 8191 
base = dD(10) ** (dD(1)/(length-1))

list1 = [ base**p for p in range (0,length)  ]
dgt.prec = 30
list2 = [ +v for v in list1 ]

values_of_x0 = tuple(list2)

def print_values_of_x0 (print_all=0) :
    '''
This function prints contents of tuple values_of_x0.
Default is to print reduced listing.
'''
    lines = []
    for p in range (0, len(values_of_x0)) :
        lines += [ "    '{}', # base ** {}".format(values_of_x0[p], p) ]
    
    new_line = '''
'''[-1:]

    str1 = new_line.join(lines)
    str2 = '({}{}{})'.format(new_line,str1,new_line)
    str3 = 'tuple([ dD(v) for v in {} ])'.format(str2)
    values_of_x01 = eval(str3)
    (values_of_x01 == values_of_x0) or ({}[3])

    if print_all : pass
    else :
        lines[15:len(values_of_x0)-15] = ( [ '    '+('#'*22) ] * 3 )
        str1 = new_line.join(lines)
        str2 = '({}{}{})'.format(new_line,str1,new_line)
        str3 = 'tuple([ dD(v) for v in {} ])'.format(str2)

    if 1 :
        str10 = '''
# Tuple values_of_x0 contains {} values from 1 through 10 both included.
# Values have precision of {}.
# Number of lines printed = {}.'''.lstrip()
        str11 = str10.format( 
            len(values_of_x0),
            dgt.prec,
            len(lines),
        )

    print_str = '''
# python code

import decimal
dD = decimal.Decimal # Decimal object is like float with (almost) unlimited precision.

{}

values_of_x0 = {}
'''
    print (print_str.format(
        str11,
        str3,
    ))
    if (len(lines) > 35) : print (str11)

print_values_of_x0 ()

Tuple values_of_x0:

# python code

import decimal
dD = decimal.Decimal # Decimal object is like float with (almost) unlimited precision.

# Tuple values_of_x0 contains 8191 values from 1 through 10 both included.
# Values have precision of 30.
# Number of lines printed = 33.

values_of_x0 = tuple([ dD(v) for v in (
    '1', # base ** 0
    '1.00028118544621897278573806728', # base ** 1
    '1.00056244995769311093431302175', # base ** 2
    '1.00084379355665441349981435563', # base ** 3
    '1.00112521626534113085090592508', # base ** 4
    '1.00140671810599776642860462823', # base ** 5
    '1.00168829910087507850455334504', # base ** 6
    '1.00196995927223008193978827786', # base ** 7
    '1.00225169864232604994400083181', # base ** 8
    '1.00253351723343251583529417399', # base ** 9
    '1.00281541506782527480043461065', # base ** 10
    '1.00309739216778638565559792132', # base ** 11
    '1.00337944855560417260761078936', # base ** 12
    '1.00366158425357322701568746780', # base ** 13
    '1.00394379928399440915366181998', # base ** 14
    ######################
    ######################
    ######################
    '9.96071693169670355246242166923', # base ** 8176
    '9.96351774033180356752203256087', # base ** 8177
    '9.96631933651352941713150174299', # base ** 8178
    '9.96912172046332775069436351828', # base ** 8179
    '9.97192489240270748518907841861', # base ** 8180
    '9.97472885255323982267776904570', # base ** 8181
    '9.97753360113655826781987911337', # base ** 8182
    '9.98033913837435864539075707594', # base ** 8183
    '9.98314546448839911780516572726', # base ** 8184
    '9.98595257970050020264571915569', # base ** 8185
    '9.98876048423254479019624844046', # base ** 8186
    '9.99156917830647816098009747521', # base ** 8187
    '9.99437866214430800330335030510', # base ** 8188
    '9.99718893596810443080299136420', # base ** 8189
    '10.0000000000000000000000000000', # base ** 8190
) ])

Dictionary dict4

edit
# python code

dict4 = dict()
for p in range (len(values_of_x0)-2,0,-1) :
    x0 = values_of_x0[p]
    sign,digits,exp = x0.as_tuple()
    dD1 = dD((0,digits[:4],0))
    if dD1 in dict4 :
        del(dict4[dD1])
        break
    dict4[dD1] = p

keys4 = sorted([ v for v in dict4 ])
start = int(keys4[0]) ; end = 10000
for key in range (start, end) :
    if key in dict4 : pass
    else :
        v = dict4[key-1]
        dict4[key] = v

def print_dict4 (print_all=0)  :
    '''
This function prints contents of dictionary dict4.
Default is to print reduced listing.
    '''
    keys4 = sorted([ key for key in dict4 ])
    lines = [ ]
    for key in keys4 :
        v = dict4[key]
        lines += [ '  ({}, {}), # dict4[{}] = {}. values_of_x0[{}] = {}'.format(key,v, key, v, v, values_of_x0[v]) ]

    new_line = '''
'''[-1:]

    str1 = new_line.join(lines)
    str2 = '({}{}{})'.format(new_line,str1,new_line)
    str3 = 'dict( {} )'.format(str2)
    dict41 = eval(str3)
    (dict41 == dict4) or ({}[4])

    if print_all : pass
    else :
        lines[15:len(keys4)-15] = ( [ '    '+('#'*22) ] * 3 )
        str1 = new_line.join(lines)
        str2 = '({}{}{})'.format(new_line,str1,new_line)
        str3 = 'dict( {} )'.format(str2)

    if 1 :
        # An example:
        x = dD('9.99456789') ; key = 9994 ; value = dict4[key]
        x0 = values_of_x0[value]
        str10 = '''
# Let x = {}
# This value of x uses key {}. Value associated with this key is {}.
# Value {} is an index into tuple values_of_x0.
# x0 = values_of_x0[{}] = {}.
#                       x - x0   {} - {}
# In this case, ratio = ------ = -------------------------------------------- = {}
#                         x0           {}'''.lstrip()


        str11 = str10.format(
            x,
            key, value,
            value,
            value,x0,
            x,x0,
            (x-x0)/x0,
            x0,
        )
        # End of an example.
    if 1 :
        str20 = '''
# Dictionary dict4 contains {} keys from {} through {} both included.
# Number of lines printed = {}.'''.lstrip()
        str21 = str20.format(
            len(keys4), keys4[0], keys4[-1],
            len(lines),
        )
    
    print_str = '''
# python code
    
import decimal
dD = decimal.Decimal # Decimal object is like float with (almost) unlimited precision.

{}

dict4 = {}

{}
'''
    
    print (print_str.format(
        str21,
        str3,
        str11,
    ))
    if (len(lines) > 35) : print (str21)

print_dict4 ()

Dictionary dict4:

# python code
   
import decimal
dD = decimal.Decimal # Decimal object is like float with (almost) unlimited precision.

# Dictionary dict4 contains 6494 keys from 3506 through 9999 both included.
# Number of lines printed = 33.

dict4 = dict( (
  (3506, 4463), # dict4[3506] = 4463. values_of_x0[4463] = 3.50697641293426289558998224666
  (3507, 4464), # dict4[3507] = 4464. values_of_x0[4464] = 3.50796252366181322886561787736
  (3508, 4465), # dict4[3508] = 4465. values_of_x0[4465] = 3.50894891166934850969761612419
  (3509, 4466), # dict4[3509] = 4466. values_of_x0[4466] = 3.50993557703483583438104568033
  (3510, 4467), # dict4[3510] = 4467. values_of_x0[4467] = 3.51092251983626422242373736544
  (3511, 4468), # dict4[3511] = 4468. values_of_x0[4468] = 3.51190974015164462271077248878
  (3512, 4469), # dict4[3512] = 4469. values_of_x0[4469] = 3.51289723805900991967070457669
  (3513, 4470), # dict4[3513] = 4470. values_of_x0[4470] = 3.51388501363641493944351495183
  (3514, 4471), # dict4[3514] = 4471. values_of_x0[4471] = 3.51487306696193645605030265189
  (3515, 4472), # dict4[3515] = 4472. values_of_x0[4472] = 3.51586139811367319756470917515
  (3516, 4473), # dict4[3516] = 4473. values_of_x0[4473] = 3.51685000716974585228607854104
  (3517, 4474), # dict4[3517] = 4474. values_of_x0[4474] = 3.51783889420829707491435315329
  (3518, 4475), # dict4[3518] = 4475. values_of_x0[4475] = 3.51882805930749149272670595406
  (3519, 4476), # dict4[3519] = 4476. values_of_x0[4476] = 3.51981750254551571175590935706
  (3520, 4477), # dict4[3520] = 4477. values_of_x0[4477] = 3.52080722400057832297044144817
    ######################
    ######################
    ######################
  (9985, 8185), # dict4[9985] = 8185. values_of_x0[8185] = 9.98595257970050020264571915569
  (9986, 8185), # dict4[9986] = 8185. values_of_x0[8185] = 9.98595257970050020264571915569
  (9987, 8185), # dict4[9987] = 8185. values_of_x0[8185] = 9.98595257970050020264571915569
  (9988, 8186), # dict4[9988] = 8186. values_of_x0[8186] = 9.98876048423254479019624844046
  (9989, 8186), # dict4[9989] = 8186. values_of_x0[8186] = 9.98876048423254479019624844046
  (9990, 8186), # dict4[9990] = 8186. values_of_x0[8186] = 9.98876048423254479019624844046
  (9991, 8187), # dict4[9991] = 8187. values_of_x0[8187] = 9.99156917830647816098009747521
  (9992, 8187), # dict4[9992] = 8187. values_of_x0[8187] = 9.99156917830647816098009747521
  (9993, 8187), # dict4[9993] = 8187. values_of_x0[8187] = 9.99156917830647816098009747521
  (9994, 8188), # dict4[9994] = 8188. values_of_x0[8188] = 9.99437866214430800330335030510
  (9995, 8188), # dict4[9995] = 8188. values_of_x0[8188] = 9.99437866214430800330335030510
  (9996, 8188), # dict4[9996] = 8188. values_of_x0[8188] = 9.99437866214430800330335030510
  (9997, 8189), # dict4[9997] = 8189. values_of_x0[8189] = 9.99718893596810443080299136420
  (9998, 8189), # dict4[9998] = 8189. values_of_x0[8189] = 9.99718893596810443080299136420
  (9999, 8189), # dict4[9999] = 8189. values_of_x0[8189] = 9.99718893596810443080299136420
) )

# Let x = 9.99456789
# This value of x uses key 9994. Value associated with this key is 8188.
# Value 8188 is an index into tuple values_of_x0.
# x0 = values_of_x0[8188] = 9.99437866214430800330335030510.
#                       x - x0   9.99456789 - 9.99437866214430800330335030510
# In this case, ratio = ------ = -------------------------------------------- = 0.0000189334286891425018292826392422
#                         x0           9.99437866214430800330335030510

Dictionary dict5

edit
# python code.

dict5 = dict()
for p in range (4463,-1,-1) :
    x0 = values_of_x0[p]
    sign,digits,exp = x0.as_tuple()
    dD1 = dD((0,(digits+(0,0,0,0))[:5],0))
    if dD1 in dict5 :
        del(dict5[dD1])
        break
    dict5[dD1] = p

keys5 = sorted([ v for v in dict5 ])

start = int(keys5[0]) ; end = keys5[-1]
for key in range (start, 35070) :
    if key in dict5 : pass
    else :
        v = dict5[key-1]
        dict5[key] = v

def print_dict5 (print_all=0)  :
    '''
This function prints contents of dictionary dict5.
Default is to print reduced listing.
    '''
    keys5 = sorted([ key for key in dict5 ])
    lines = [ ]
    for key in keys5 :
        v = dict5[key]
        lines += [ '  ({}, {}), # dict5[{}] = {}. values_of_x0[{}] = {}'.format(key,v, key, v, v, values_of_x0[v]) ]

    new_line = '''
'''[-1:]

    str1 = new_line.join(lines)
    str2 = '({}{}{})'.format(new_line,str1,new_line)
    str3 = 'dict( {} )'.format(str2)
    dict51 = eval(str3)
    (dict51 == dict5) or ({}[5])

    if print_all : pass
    else :
        lines[15:len(keys5)-15] = ( [ '    '+('#'*22) ] * 3 )
        str1 = new_line.join(lines)
        str2 = '({}{}{})'.format(new_line,str1,new_line)
        str3 = 'dict( {} )'.format(str2)

    if 1 :
        # An example:
        x = dD('3.50667891') ; key = 35066 ; value = dict5[key]
        x0 = values_of_x0[value]
        str10 = '''
# Let x = {}
# This value of x uses key {}. Value associated with this key is {}.
# Value {} is an index into tuple values_of_x0.
# x0 = values_of_x0[{}] = {}.
#                       x - x0   {} - {}
# In this case, ratio = ------ = -------------------------------------------- = {}
#                         x0           {}'''.lstrip()


        str11 = str10.format(
            x,
            key, value,
            value,
            value,x0,
            x,x0,
            (x-x0)/x0,
            x0,
        )
        # End of an example.
    if 1 :
        str20 = '''
# Dictionary dict5 contains {} keys from {} through {} both included.
# Number of lines printed = {}.'''.lstrip()
        str21 = str20.format(
            len(keys5), keys5[0], keys5[-1],
            len(lines),
        )

    print_str = '''
# python code

import decimal
dD = decimal.Decimal # Decimal object is like float with (almost) unlimited precision.

{}

dict5 = {}

{}
'''
    print (print_str.format(
        str21,
        str3,
        str11,
    ))
    if (len(lines) > 35) : print (str21)

print_dict5 ()

Dictionary dict5:

# python code

import decimal
dD = decimal.Decimal # Decimal object is like float with (almost) unlimited precision.

# Dictionary dict5 contains 25070 keys from 10000 through 35069 both included.
# Number of lines printed = 33.

dict5 = dict( (
  (10000, 0), # dict5[10000] = 0. values_of_x0[0] = 1
  (10001, 0), # dict5[10001] = 0. values_of_x0[0] = 1
  (10002, 1), # dict5[10002] = 1. values_of_x0[1] = 1.00028118544621897278573806728
  (10003, 1), # dict5[10003] = 1. values_of_x0[1] = 1.00028118544621897278573806728
  (10004, 1), # dict5[10004] = 1. values_of_x0[1] = 1.00028118544621897278573806728
  (10005, 2), # dict5[10005] = 2. values_of_x0[2] = 1.00056244995769311093431302175
  (10006, 2), # dict5[10006] = 2. values_of_x0[2] = 1.00056244995769311093431302175
  (10007, 2), # dict5[10007] = 2. values_of_x0[2] = 1.00056244995769311093431302175
  (10008, 3), # dict5[10008] = 3. values_of_x0[3] = 1.00084379355665441349981435563
  (10009, 3), # dict5[10009] = 3. values_of_x0[3] = 1.00084379355665441349981435563
  (10010, 3), # dict5[10010] = 3. values_of_x0[3] = 1.00084379355665441349981435563
  (10011, 4), # dict5[10011] = 4. values_of_x0[4] = 1.00112521626534113085090592508
  (10012, 4), # dict5[10012] = 4. values_of_x0[4] = 1.00112521626534113085090592508
  (10013, 4), # dict5[10013] = 4. values_of_x0[4] = 1.00112521626534113085090592508
  (10014, 5), # dict5[10014] = 5. values_of_x0[5] = 1.00140671810599776642860462823
    ######################
    ######################
    ######################
  (35055, 4461), # dict5[35055] = 4461. values_of_x0[4461] = 3.50500502300735826561653416805
  (35056, 4461), # dict5[35056] = 4461. values_of_x0[4461] = 3.50500502300735826561653416805
  (35057, 4461), # dict5[35057] = 4461. values_of_x0[4461] = 3.50500502300735826561653416805
  (35058, 4461), # dict5[35058] = 4461. values_of_x0[4461] = 3.50500502300735826561653416805
  (35059, 4462), # dict5[35059] = 4462. values_of_x0[4462] = 3.50599057940875233062564717952
  (35060, 4462), # dict5[35060] = 4462. values_of_x0[4462] = 3.50599057940875233062564717952
  (35061, 4462), # dict5[35061] = 4462. values_of_x0[4462] = 3.50599057940875233062564717952
  (35062, 4462), # dict5[35062] = 4462. values_of_x0[4462] = 3.50599057940875233062564717952
  (35063, 4462), # dict5[35063] = 4462. values_of_x0[4462] = 3.50599057940875233062564717952
  (35064, 4462), # dict5[35064] = 4462. values_of_x0[4462] = 3.50599057940875233062564717952
  (35065, 4462), # dict5[35065] = 4462. values_of_x0[4462] = 3.50599057940875233062564717952
  (35066, 4462), # dict5[35066] = 4462. values_of_x0[4462] = 3.50599057940875233062564717952
  (35067, 4462), # dict5[35067] = 4462. values_of_x0[4462] = 3.50599057940875233062564717952
  (35068, 4462), # dict5[35068] = 4462. values_of_x0[4462] = 3.50599057940875233062564717952
  (35069, 4463), # dict5[35069] = 4463. values_of_x0[4463] = 3.50697641293426289558998224666
) )

# Let x = 3.50667891
# This value of x uses key 35066. Value associated with this key is 4462.
# Value 4462 is an index into tuple values_of_x0.
# x0 = values_of_x0[4462] = 3.50599057940875233062564717952.
#                       x - x0   3.50667891 - 3.50599057940875233062564717952
# In this case, ratio = ------ = -------------------------------------------- = 0.000196329846203907638094539889319
#                         x0           3.50599057940875233062564717952

Decision Points

edit
# python code

decision_points=[]
for p in range (0, len(values_of_x0)-1) :
    a,b = values_of_x0[p], values_of_x0[p+1]
    #            ab
    # ratio = ---------
    #         (a + b)/2
    decision_point = 2*a*b/(a+b)
    decision_points += [ decision_point ]
decision_points = tuple(decision_points)

def print_decision_points(print_all=0) :
    '''
This function prints contents of tuple decision_points.
Default is to print reduced listing.
'''
    lines = []
    for p in range (0, len(decision_points)) :
        lines += [ "    '{}', # Decision point for values_of_x0[{}], {}".format(decision_points[p], p, values_of_x0[p]) ]
    
    new_line = '''
'''[-1:]

    str1 = new_line.join(lines)
    str2 = '({}{}{})'.format(new_line,str1,new_line)
    str3 = 'tuple([ dD(v) for v in {} ])'.format(str2)
    decision_points1 = eval(str3)
    (decision_points1 == decision_points) or ({}[3])

    if print_all : pass
    else :
        lines[15:len(values_of_x0)-16] = ( [ '    '+('#'*22) ] * 3 )
        str1 = new_line.join(lines)
        str2 = '({}{}{})'.format(new_line,str1,new_line)
        str3 = 'tuple([ dD(v) for v in {} ])'.format(str2)

    if 1 :
        # Check the decision points:
        list1 = []
        for p in range (0, len(decision_points)) :
            x = decision_points[p]
            x0 = values_of_x0[p]
            list1 += [ (x-x0)/x0 ]
            x0 = values_of_x0[p+1]
            list1 += [ (x-x0)/x0 ]
        list2 = sorted(list1)

        str11 = '''
# If x == {}, initial x0 chosen is values_of_x0[8188].
# Ratio (x-x0)/x0 for this value of x0 =  {}
# However, x >= decision_points[8188],
# therefore x0 chosen is values_of_x0[8189].
# Ratio (x-x0)/x0 for this value of x0 = {}

# Minimum value of (x-x0)/x0 = {}
# Maximum value of (x-x0)/x0 =  {}'''.lstrip()
        x = dD('9.996')
        str12 = str11.format(
            x,
            ( x - values_of_x0[8188] )/values_of_x0[8188],
            ( x - values_of_x0[8189] )/values_of_x0[8189],
            list2[0],
            list2[-1],
        )
    if 2 :
        str20 = '''
# Tuple decision_points contains {} values.
# Values have precision of {}.
# Number of lines printed = {}.'''.lstrip()
        str21 = str20.format(
            len(decision_points),
            dgt.prec,
            len(lines),
        )

    print_str = '''
# python code

import decimal
dD = decimal.Decimal # Decimal object is like float with (almost) unlimited precision.

{}

decision_points = {}

{}
'''
    print (print_str.format(
        str21,
        str3,
        str12,
    ))
    if (len(lines) > 35) : print (str21)

print_decision_points ()

Tuple decision_points:

# python code

import decimal
dD = decimal.Decimal # Decimal object is like float with (almost) unlimited precision.

# Tuple decision_points contains 8190 values.
# Values have precision of 30.
# Number of lines printed = 33.

decision_points = tuple([ dD(v) for v in (
    '1.00014057295957430428168296256', # Decision point for values_of_x0[0], 1
    '1.00042179793286364128979317200', # Decision point for values_of_x0[1], 1.00028118544621897278573806728
    '1.00070310198252258057883287150', # Decision point for values_of_x0[2], 1.00056244995769311093431302175
    '1.00098448513078624642079583976', # Decision point for values_of_x0[3], 1.00084379355665441349981435563
    '1.00126594739989601528101601040', # Decision point for values_of_x0[4], 1.00112521626534113085090592508
    '1.00154748881209951757619324607', # Decision point for values_of_x0[5], 1.00140671810599776642860462823
    '1.00182910938965063943291344401', # Decision point for values_of_x0[6], 1.00168829910087507850455334504
    '1.00211080915480952444666311171', # Decision point for values_of_x0[7], 1.00196995927223008193978827786
    '1.00239258812984257544133855191', # Decision point for values_of_x0[8], 1.00225169864232604994400083181
    '1.00267444633702245622924979608', # Decision point for values_of_x0[9], 1.00253351723343251583529417399
    '1.00295638379862809337161942522', # Decision point for values_of_x0[10], 1.00281541506782527480043461065
    '1.00323840053694467793957641743', # Decision point for values_of_x0[11], 1.00309739216778638565559792132
    '1.00352049657426366727564516130', # Decision point for values_of_x0[12], 1.00337944855560417260761078936
    '1.00380267193288278675572977430', # Decision point for values_of_x0[13], 1.00366158425357322701568746780
    '1.00408492663510603155159386566', # Decision point for values_of_x0[14], 1.00394379928399440915366181998
    ######################
    ######################
    ######################
    '9.95931672423813306357100081673', # Decision point for values_of_x0[8175], 9.95791691038684497262024697178
    '9.96211713915527404135384252174', # Decision point for values_of_x0[8176], 9.96071693169670355246242166923
    '9.96491834150833309369022259996', # Decision point for values_of_x0[8177], 9.96351774033180356752203256087
    '9.96772033151872574057278088598', # Decision point for values_of_x0[8178], 9.96631933651352941713150174299
    '9.97052310940792976081594615060', # Decision point for values_of_x0[8179], 9.96912172046332775069436351828
    '9.97332667539748520956221068667', # Decision point for values_of_x0[8180], 9.97192489240270748518907841861
    '9.97613102970899443579332740474', # Decision point for values_of_x0[8181], 9.97472885255323982267776904570
    '9.97893617256412209984643082198', # Decision point for values_of_x0[8182], 9.97753360113655826781987911337
    '9.98174210418459519093508332990', # Decision point for values_of_x0[8183], 9.98033913837435864539075707594
    '9.98454882479220304467524812459', # Decision point for values_of_x0[8184], 9.98314546448839911780516572726
    '9.98735633460879736061619018673', # Decision point for values_of_x0[8185], 9.98595257970050020264571915569
    '9.99016463385629221977630669417', # Decision point for values_of_x0[8186], 9.98876048423254479019624844046
    '9.99297372275666410218388825624', # Decision point for values_of_x0[8187], 9.99156917830647816098009747521
    '9.99578360153195190442281235396', # Decision point for values_of_x0[8188], 9.99437866214430800330335030510
    '9.99859427040425695718317037442', # Decision point for values_of_x0[8189], 9.99718893596810443080299136420
) ])

# If x == 9.996, initial x0 chosen is values_of_x0[8188].
# Ratio (x-x0)/x0 for this value of x0 =  0.000162224977710033689939296541400
# However, x >= decision_points[8188],
# therefore x0 chosen is values_of_x0[8189].
# Ratio (x-x0)/x0 for this value of x0 = -0.000118927027959514803376227947800

# Minimum value of (x-x0)/x0 = -0.000140572959574304281682962568892
# Maximum value of (x-x0)/x0 =  0.000140572959574304281682962568536

values_of_ln_x0_

edit
# python code

Precision = dgt.prec = 115 # Preparing for values containing 110 places of decimal numbers.
Tolerance = Decimal('1e-' + str( Precision-3 ))

ln_x_Global_Flag = 0

def ln_x (x, x0, C) :
    '''
Return ln(x) for x close to x0.
ln_x_ = ln_x (x, x0, C) 
C is the constant of integration. Usually C = ln(x0).
If ln_x_Global_Flag is non-zero, this function prints useful information.
    '''
    global ln_x_Global_Flag
    
    if ln_x_Global_Flag :
        thisName = 'ln_x (x, x0, C=0) :'
        print (thisName)
        print ('  x =', x)
        print ('  x0 =', x0)
        print ('  C =', C)

    status = 1 ; limit = dgt.prec
    sum = progressiveValue = multiplier = (x - x0)/x0

    progressiveValue *= multiplier
    addendum = progressiveValue / 2
    sum -= addendum

    min,max = sorted((C,abs(progressiveValue)))
    limit_small = Tolerance * max

    if ln_x_Global_Flag :
        print ('  multiplier =', multiplier)
        print ('  limit =', limit)
        print()
        print ('  addendum =', addendum)
        print ('  sum      =', sum)

    for p in range (3, limit, 2) :
        progressiveValue *= multiplier
        addendum = progressiveValue / p
        sum += addendum
 
        progressiveValue *= multiplier
        addendum = progressiveValue / (p+1)
        sum -= addendum

        if ln_x_Global_Flag :
            print()
            print ('  addendum =', addendum)
            print ('       sum =', sum)

        if (abs(addendum) < limit_small) :
            status = 0
            break
    
    if (status) :
        print ('ln_x():')
        print ('  error: count expired, p =',p)
        return

    output = sum + C
    
    if ln_x_Global_Flag :
        print ('  p =', p)
        print ('  output =', output)

    return output

values_of_ln_x0_ = [ Decimal(0) ]
for p in range(1, len(values_of_x0),1) :
    # Size of list values_of_ln_x0_ increases with every pass through this loop.
    x = values_of_x0[p]
    x0 = values_of_x0[p-1]
    C = values_of_ln_x0_[p-1]
    ln = ln_x (x, x0, C)
    values_of_ln_x0_ += [ ln ]

Precision = dgt.prec = 110 
Tolerance = Decimal('1e-' + str( Precision-3 ))

dC = decimal.Context
values_of_ln_x0_ = tuple([ dC(prec=Precision,rounding=decimal.ROUND_HALF_UP).create_decimal(v) for v in values_of_ln_x0_])

def print_values_of_ln_x0_ (print_all=0) :
    '''
This function prints contents of tuple values_of_ln_x0_.
Default is to print reduced listing.
'''
    lines = []
    for p in range (0, len(values_of_ln_x0_)) :
        x = values_of_x0[p] ; logn_x_ = values_of_ln_x0_[p]
        (logn_x_ == x.ln()) or ({}[17])
        lines += [ "    '{}', # ln(x) for x = values_of_x0[{}] = {}.".format(logn_x_, p, x) ]
    
    new_line = '''
'''[-1:]

    str1 = new_line.join(lines)
    str2 = '({}{}{})'.format(new_line,str1,new_line)
    str3 = 'tuple([ dD(v) for v in {} ])'.format(str2)
    values_of_ln_x0_1 = eval(str3)
    (values_of_ln_x0_1 == values_of_ln_x0_) or ({}[3])

    if print_all : pass
    else :
        lines[15:len(values_of_ln_x0_)-15] = ( [ '    '+('#'*22) ] * 3 )
        str1 = new_line.join(lines)
        str2 = '({}{}{})'.format(new_line,str1,new_line)
        str3 = 'tuple([ dD(v) for v in {} ])'.format(str2)

    if 1 :
        str20 = '''
# Tuple values_of_ln_x0_ contains {} values.
# Values have precision of {}.
# Number of lines printed = {}.'''.lstrip()
        str21 = str20.format(
            len(values_of_ln_x0_),
            dgt.prec,
            len(lines),
        )

    print_str = '''
# python code

import decimal
dD = decimal.Decimal # Decimal object is like float with (almost) unlimited precision.

{}

values_of_ln_x0_ = {}

# All values match corresponding values calculated from python's method .ln().
'''
    print (print_str.format(
        str21,
        str3,
    ))
    if (len(lines) > 35) : print (str21)

print_values_of_ln_x0_ ()

Tuple values_of_ln_x0_:

# python code
import decimal
dD = decimal.Decimal # Decimal object is like float with (almost) unlimited precision.

# Tuple values_of_ln_x0_ contains 8191 values.
# Values have precision of 110.
# Number of lines printed = 33.

values_of_ln_x0_ = tuple([ dD(v) for v in (
    '0', # ln(x) for x = values_of_x0[0] = 1.
    '0.00028114592100049397851257526958789318557823685315140509591146945610630681924483554634842715913155791553935763353', # ln(x) for x = values_of_x0[1] = 1.00028118544621897278573806728.
    '0.00056229184200098795702515053832076377529815817685091034900099838032371576474647395210890353807586706979025309841', # ln(x) for x = values_of_x0[2] = 1.00056244995769311093431302175.
    '0.00084343776300148193553772580559921306036271356639510059614615649527672916175199470705511306484712247456495136785', # ln(x) for x = values_of_x0[3] = 1.00084379355665441349981435563.
    '0.0011245836840019759140503010760592633243233373666630274912240526872189379027309580785200788485985603865985895688', # ln(x) for x = values_of_x0[4] = 1.00112521626534113085090592508.
    '0.0014057296050024698925628763418989224560236605191226558916675419561961081724994394224778473772989675950066240433', # ln(x) for x = values_of_x0[5] = 1.00140671810599776642860462823.
    '0.0016868755260029638710754516132125138240706054425728603309033120607959071382243819085331207823151560952524126555', # ln(x) for x = values_of_x0[6] = 1.00168829910087507850455334504.
    '0.0019680214470034578495880268872333649791972073653457158404410113008355450069732509641759673340415353071544323205', # ln(x) for x = values_of_x0[7] = 1.00196995927223008193978827786.
    '0.0022491673680039518281006021580778932979673021988265352275636839430354663150269526071071437607450560006442621246', # ln(x) for x = values_of_x0[8] = 1.00225169864232604994400083181.
    '0.0025303132890044458066131774196426391914772962305290824563142073882759834795702976123051014571348552310189175327', # ln(x) for x = values_of_x0[9] = 1.00253351723343251583529417399.
    '0.0028114592100049397851257526950841486394900305702168719174622980317602779030546368107920305020685647504214850020', # ln(x) for x = values_of_x0[10] = 1.00281541506782527480043461065.
    '0.0030926051310054337636383279576467230904015964551099672846920959011633015793790942523210207705866150801840718264', # ln(x) for x = values_of_x0[11] = 1.00309739216778638565559792132.
    '0.0033737510520059277421509032273666711656003353833161378685286907465997110550477881401427392163316523076635049655', # ln(x) for x = values_of_x0[12] = 1.00337944855560417260761078936.
    '0.0036548969730064217206634785007033901080823462730164946725801425392961788141621195388687950276169252526202813317', # ln(x) for x = values_of_x0[13] = 1.00366158425357322701568746780.
    '0.0039360428940069156991760537694132046752291888691499866508887763250737472392296047255077029503512257389803956675', # ln(x) for x = values_of_x0[14] = 1.00394379928399440915366181998.
    ######################
    ######################
    ######################
    '2.2986490501000387683188154009156080387928397456918301259039789087944336216064685316414378199045428924326799354', # ln(x) for x = values_of_x0[8176] = 9.96071693169670355246242166923.
    '2.2989301960210392622973279761851826912850498262636764478593466003783569959365230606881295712717359785963112572', # ln(x) for x = values_of_x0[8177] = 9.96351774033180356752203256087.
    '2.2992113419420397562758405514538127154368379767714938128234341386785761356659428151509538766438052956987514456', # ln(x) for x = values_of_x0[8178] = 9.96631933651352941713150174299.
    '2.2994924878630402502543531267234795446120177448761439909215905629390155692208202036169724706742616903146745976', # ln(x) for x = values_of_x0[8179] = 9.96912172046332775069436351828.
    '2.2997736337840407442328657019924935957228985155357974105355104395265542601189816673651603550100698554337262110', # ln(x) for x = values_of_x0[8180] = 9.97192489240270748518907841861.
    '2.3000547797050412382113782772620075034105144024446410997113100105048869297857113614199956326399453812234259798', # ln(x) for x = values_of_x0[8181] = 9.97472885255323982267776904570.
    '2.3003359256260417321898908525304842706062415677704389700357254056059757438662458766613085787045702337983018714', # ln(x) for x = values_of_x0[8182] = 9.97753360113655826781987911337.
    '2.3006170715470422261684034277999240939447294182933534442617229885402608324814372163790494646489096111864238087', # ln(x) for x = values_of_x0[8183] = 9.98033913837435864539075707594.
    '2.3008982174680427201469160030695937857213769448822598470814633753680217668218642029270879455834911773531417718', # ln(x) for x = values_of_x0[8184] = 9.98314546448839911780516572726.
    '2.3011793633890432141254285783381842630937332590762005140545211954364744522739221910731492477352251364727532941', # ln(x) for x = values_of_x0[8185] = 9.98595257970050020264571915569.
    '2.3014605093100437081039411536072957843624648926396223086157833390784873434028789437068207364140323800128952846', # ln(x) for x = values_of_x0[8186] = 9.98876048423254479019624844046.
    '2.3017416552310442020824537288772066438368127181180454803304105302438376670970053383184297088473645195882839920', # ln(x) for x = values_of_x0[8187] = 9.99156917830647816098009747521.
    '2.3020228011520446960609663041459434200397763370975986092768268975848700083257305096479892286265624964942134938', # ln(x) for x = values_of_x0[8188] = 9.99437866214430800330335030510.
    '2.3023039470730451900394788794156639713397781053105254292750160375440587140647147489289589658979929574060205262', # ln(x) for x = values_of_x0[8189] = 9.99718893596810443080299136420.
    '2.3025850929940456840179914546843642076011014886287729760333279009675726096773524802359972050895982983419677840', # ln(x) for x = values_of_x0[8190] = 10.0000000000000000000000000000.
) ])

# All values match corresponding values calculated from python's method .ln().

nat_logs_of_10_integers

edit

This data structure is included because this author believes that it would be handy to have natural logarithms of the small integers readily available.

def simple_ln (x, flag = 0) :
    '''
This function calculates ln(x) using the slow, simple method.
Result is accurate to precision as in dgt.prec.
If flag, this function also calculates x.ln() for internal checking.
    '''
    
    x_ = dD(str(x))
    old_precision = dgt.prec
    pre = precision = dgt.prec = int((dgt.prec + 5)*10/3)
    lnx = ([ root for root in [x_] for p in range (1,pre+1) for root in [root.sqrt()] ][-1] - 1) * (1 << pre)
    dgt.prec = old_precision
    lnx += 0
    if flag : (x_.ln() == lnx) or ({}[13])
    return lnx
# python code

nat_logs_of_10_integers = [0,dD(0)]

for x in range(2,11) :
    nlog = simple_ln (x)
    nat_logs_of_10_integers += [ nlog ]

nat_logs_of_10_integers = tuple(nat_logs_of_10_integers)

def print_nat_logs_of_10_integers() :
    '''
This function prints contents of tuple nat_logs_of_10_integers.
'''
    lines = []
    lines += [ "    '0', # Filler." ]
    for x in range (1, len(nat_logs_of_10_integers)) :
        logn_x_ = nat_logs_of_10_integers[x]
        ( logn_x_ == dD(x).ln() ) or ({}[30])
        lines += [ "    '{}', # ln({}) = nat_logs_of_10_integers[{}]".format(logn_x_, x, x) ]
    
    new_line = '''
'''[-1:]

    str1 = new_line.join(lines)
    str2 = '({}{}{})'.format(new_line,str1,new_line)
    str3 = 'tuple([ dD(v) for v in {} ])'.format(str2)
    nat_logs_of_10_integers1 = eval(str3)
    (nat_logs_of_10_integers1 == nat_logs_of_10_integers) or ({}[3])

    print_str = '''
import decimal
dD = decimal.Decimal

# Tuple nat_logs_of_10_integers contains {} values:
#    1 filler and ln(x) for x in (1,2,3,4,5,6,7,8,9,10).
# Values have precision of {}.
# Number of lines printed = {}.
# All values match corresponding values calculated from python's method .ln().

nat_logs_of_10_integers = {}
'''
    print (print_str.format(
        len(nat_logs_of_10_integers),
        dgt.prec,
        len(lines),
        str3,
    ))

print_nat_logs_of_10_integers()

Tuple nat_logs_of_10_integers:

import decimal
dD = decimal.Decimal
    
# Tuple nat_logs_of_10_integers contains 11 values:
#    1 filler and ln(x) for x in (1,2,3,4,5,6,7,8,9,10).
# Values have precision of 110.
# Number of lines printed = 11.
# All values match corresponding values calculated from python's method .ln().
    
nat_logs_of_10_integers = tuple([ dD(v) for v in (
    '0', # Filler.
    '0', # ln(1) = nat_logs_of_10_integers[1] 
    '0.69314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641868754200148102', # ln(2) = nat_logs_of_10_integers[2]
    '1.0986122886681096913952452369225257046474905578227494517346943336374942932186089668736157548137320887879700291', # ln(3) = nat_logs_of_10_integers[3]
    '1.3862943611198906188344642429163531361510002687205105082413600189867872439393894312117266539928373750840029620', # ln(4) = nat_logs_of_10_integers[4]
    '1.6094379124341003746007593332261876395256013542685177219126478914741789877076577646301338780931796107999663030', # ln(5) = nat_logs_of_10_integers[5]
    '1.7917594692280550008124773583807022727229906921830047058553743431308879151883036824794790818101507763299715101', # ln(6) = nat_logs_of_10_integers[6]
    '1.9459101490553133051053527434431797296370847295818611884593901499375798627520692677876584985878715269930616942', # ln(7) = nat_logs_of_10_integers[7]
    '2.0794415416798359282516963643745297042265004030807657623620400284801808659090841468175899809892560626260044431', # ln(8) = nat_logs_of_10_integers[8]
    '2.1972245773362193827904904738450514092949811156454989034693886672749885864372179337472315096274641775759400581', # ln(9) = nat_logs_of_10_integers[9]
    '2.3025850929940456840179914546843642076011014886287729760333279009675726096773524802359972050895982983419677840', # ln(10) = nat_logs_of_10_integers[10]
) ])

Accessing the data structures

edit

Function natural_log()

edit
# python code.

natural_log_Global_Flag = 0

def natural_log (x) :
    '''
This function calculates x0 and ln(x0), and invokes function ln_x().
ln_x_ = natural_log (x)
x is limited to (10 >= x >= 1).
    '''
    (10 >= x >= 1) or ({}[89])
    if x == 1 : return dD(0)
    if x == 10 : return values_of_ln_x0_[-1]

    while 1 :
        '''
This code is written for speed.
If x == 5.67 key generated is 5670. p = dict4[5670].
If x == 2.3456789 key generated is 23456. p = dict5[23456].
Check values_of_x0[p], values_of_x0[p-1]. Return appropriate value of p.
Result must be found with max of 2 tests. Anything else means internal error.
    '''
        if x > dD('3.506') :
            p = dict4[ int(x * 1_000) ]
            if x >= values_of_x0[p] : break
            p -= 1
            if x >= values_of_x0[p] : break
            ({}[13])
        p = dict5[ int(x * 10_000) ]
        if x >= values_of_x0[p] : break
        p -= 1
        if x >= values_of_x0[p] : break
        ({}[14])
    
    if x >= decision_points[p] : p += 1
    x0 = values_of_x0[p]
    C = values_of_ln_x0_[p]
    
    if natural_log_Global_Flag :
        print ('natural_log (x) :')
        print ('  x =', x)
        print ('  x0 =', x0)
        print ('  C =', C)
        print ('  multiplier =', (x-x0)/x0)
    
    if x == x0 : return C
    
    ln_x_ = ln_x (x, x0, C)
    if natural_log_Global_Flag :
        print ('  ln(x) =', ln_x_)
    return ln_x_

Testing Function natural_log()

edit

For accuracy

edit

This test compares natural_log(x) with python's calculation, x.ln(), using almost 9,000,000 values of x from 1 to 10.

# python code.

count = count1 = count2 = count3 = 0
for X in range(100_000_001, 1_000_000_000,101) : # 8910892
    count += 1
    x = dD(X)/100_000_000
    lnx = natural_log (x) ; lnx_ = x.ln()
    # test 1
    if lnx == lnx_ :
        # Both values are equal.
        count1 += 1 ; continue
    # test 2
    str1 = str(lnx).upper() ; str2 = str(lnx_)
    if 'E' not in str1 :
        if str1[:-1] == str2[:-1] :
            # Both values are equal except for least significant digit.
            count2 += 1 ; continue
    # test 3
    v1 = dC(prec=dgt.prec-1,rounding=decimal.ROUND_HALF_UP).create_decimal(lnx)
    v2 = dC(prec=dgt.prec-1,rounding=decimal.ROUND_HALF_UP).create_decimal(lnx_)
    if v1 == v2 :
        # With precision reduced by 1, both values are equal.
        count3 += 1 ; continue
    ({}[17])

values = count1,count2,count3,count
len1 = sorted([ len(str(v)) for v in values ])[-1]
a,b,c,d = [ ((' '*len1)+str(v))[-len1:] for v in values ]
str20 = 'count == count1+count2+count3'
str1 = '''
count1 = {}  Both values equal.
count2 = {}  Both values equal except for least significant digit.
count3 = {}  Both values equal with precision reduced by 1.
count  = {}
{}: {}'''.format(a,b,c,d,str20, eval(str20))
print (str1)
count1 = 6687475  Both values equal.
count2 = 2001406  Both values equal except for least significant digit.
count3 =  222011  Both values equal with precision reduced by 1.
count  = 8910892
count == count1+count2+count3: True

Considering that function natural_log(x) was written for speed, this author finds these results quite satisfactory.

For speed

edit
# python code.

count = 0
for X in range(100_000_001, 1_000_000_000, 1001) : # 899101
    count += 1
    x = dD(X)/100_000_000
    if 1 : natural_log (x)
    else : x.ln()
sx = 'count' ; print (sx, '=', eval(sx))
python3 ./wiki_005.py > j1q 2> j2q  16.85s user 0.02s system 99% cpu 16.878 total
count = 899101
# python code.

count = 0
for X in range(100_000_001, 1_000_000_000, 1001) : # 899101
    count += 1
    x = dD(X)/100_000_000
    if 0 : natural_log (x)
    else : x.ln()
sx = 'count' ; print (sx, '=', eval(sx))
python3 ./wiki_005.py > j1q 2> j2q  77.01s user 0.10s system 99% cpu 1:17.11 total
count = 899101

This test indicates that this implementation of ln(x) is four times faster than python's method x.ln().

Putting all together

edit
# python code.

def make_Decimal_number_clean(number) :
    '''
Number such as 0.9999999999999999999999999999999999999999
is returned as 1.
Number 0.9999999999999999999999999999999999999999 is described as "raw."
Number 1  is described as "clean."
Number 1E-103  becomes 0.
    '''
    if abs(number) < Tolerance : return dD(0)
    dgt.prec -= 2
    dD1 = (+number).normalize()
    dgt.prec += 2
    sign,digits,exponent = dD1.as_tuple()
    if len(digits) < (dgt.prec - (dgt.prec >> 2)) : return dD1
    return number
# python code.

def sum_zero(values) :
  '''
This function calculates sum of all values.
However, if sum is close to zero and Tolerance permits, sum
is returned as zero.
Useful for testing 2 numbers for being "almost" equal.
For example:
  let v1 be 1.9999999999999999999999999999999999999
  let v2 be 2
sum_zero((v1,-v2)) returns 0.
'''
  sump = sumn = 0
  for v in values :
    if v > 0 : sump += v
    else : sumn -= v
  sum = sump - sumn
  if abs(sum) < Tolerance : return dD(0)
  min,max = sorted((sump,sumn))
  if abs(sum) <= Tolerance*min : return dD(0)
  return sum
# python code.

import sys

def natural_logarithm (number, flag=0) :
    '''
ln_x_ = natural_logarithm (x  [,flag])
ln(number) = ln(standard_number * (10 ** exponent))
= ln(standard_number) + ln(10 ** exponent))
= ln(standard_number) + exponent*ln(10)

For example:
ln(12345.6789)
= ln(1.23456789 * 10**4)
= ln(1.23456789) + 4(ln(10))
Value 1.23456789 is called standard_number and 4 is exponent.

print_ = flag & 1
print_all = flag & 2
check = flag & 4
do_not_clean = flag & 8
    '''
    thisName = 'natural_logarithm (number) :'

    error = ''
    try :
        number = dD(str(number)).normalize()
        print_ = flag & 1
    except : v1,v2,v3 = error = sys.exc_info()
    if error :
        print ()
        print (thisName)
        print ('  Input not recognized.')
        print (' ', v1)
        print (' ', v2)
        print (' ', v3)
        print ()
        return

    print_all = flag & 2
    check = flag & 4
    if print_all : print_ = 1
    if print_ : check = 4
    do_not_clean = flag & 8

    if number <= 0 :
        print()
        print (thisName)
        print ('  Input number must be > 0.')
        print ()
        return

    if print_ :
        print()
        print(thisName)
        print('  Input number =', number)
    if print_all :
        print('  flag =', bin(flag))

    if 10 >= number >= 1 :
        ln_x_ = natural_log (number)
    else :
        sign, digits, exponent = number.as_tuple()
        if print_all :
            print(thisName)
            print('  digits =', digits)
            print('  exponent =', exponent)

        if (len(digits) == 1) :
            standard_number = dD(digits[0])
        else :
            digits = list(digits)
            exponent += (len(digits)-1)
            digits[1:1] = '.' 
            standard_number = dD( ''.join([str(v) for v in digits]) )

        if standard_number == 1 : standard_log = 0
        else : standard_log = natural_log (standard_number) 
        ln_x_ = standard_log + exponent * nat_logs_of_10_integers[10]

        if print_all :
            print(thisName)
            print('  standard_number =', standard_number)
            print('  ln of standard_number =', standard_log)
        
    if check:
        # Some internal checking.
        b = number ; lnb = ln_x_ ; count = 0
        if 1 :
            # Two values in each of the following tuples should be equal.
            b__2 = ( natural_logarithm(b**2),                       2*lnb )
            b_2  = ( natural_logarithm(b*2), (lnb + nat_logs_of_10_integers[2]) )
            b_5  = ( natural_logarithm(b/5), (lnb - nat_logs_of_10_integers[5]) )
            b_r  = ( natural_logarithm(1/b),                         -lnb )
        for str1 in 'b__2  b_2  b_5  b_r'.split() :
            v1,v2 = eval(str1)
            sum = sum_zero((v1,-v2))
            if sum :
                count += 1
                if not print_ :
                    print_ = 1 ; print()
                print (thisName)
                if count == 1:
                    print ('  number =', b)
                    print ('  ln_x_  =', ln_x_)
                    print ('  precision =', dgt.prec)
                    print ('  Tolerance =', Tolerance)
                print ('  Test {} failed.'.format(str1))
                print ('  v1 =', v1)
                print ('  v2 =', v2)
                print ('  sum =', sum)
        if count :
            print ('  Number of errors detected =', count)
            print() ; return

    if do_not_clean : pass
    else : ln_x_ = make_Decimal_number_clean(ln_x_) 
  
    if print_ :
        print(thisName)
        if int(ln_x_) == ln_x_ : print('  Output =', int(ln_x_))
        else                   : print('  Output =',     ln_x_ )
        print()
    
    return ln_x_