zlacker

[return to "My Favorite Programming Problem to Teach: Digit Length"]
1. jepler+N3[view] [source] 2019-11-10 22:44:41
>>jstrie+(OP)
But the math.log10 solution is unfortunately "wrong" too, at least in my python3 implementation.

    import math

    def digitLengthCorrect(n):
        return len(str(n))

    def digitLengthClever2(n):
        return 1 if n == 0 else (math.floor(math.log10(n)) + 1)

    testcases = (
        [10 ** i for i in range(300)] +
        [(10 ** i) - 1 for i in range(300)]
    )

    for t in testcases:
        a = digitLengthCorrect(t)
        b = digitLengthClever2(t)
        assert a == b, (t, a, b)
◧◩
2. gspetr+qv[view] [source] 2019-11-11 05:24:59
>>jepler+N3
Good point. To indemnify youself from this type of data loss, change math.log10() to np.log10() and use Decimal() for tasks involving precise number crunching.

EDIT: Setting Decimal module's precision manually via getcontext() may be required if you work with "long" numbers.

    import math
    import numpy as np
    from decimal import getcontext, Decimal

    def digit_length_correct(n):
        return len(str(n))
    
    def digit_length_clever_2(n):
        if n ==0:
            return 1
        else:
            return math.floor((np.log10(Decimal(n)))) + 1 # You can use np.floor() and eschew the use of math. module altogether, but I left it intact to show the minimal necessary modifications
    
    def generate_cases(n):
        getcontext().prec = n + 3
        return (
        [10 ** i for i in range(n)] +
        [(10 ** i) - 1 for i in range(n)]
    )
    
    cases = generate_cases(300)
    
    for t in cases:
        a = digit_length_correct(t)
        b = digit_length_clever_2(t)
        assert a == b, (t, a, b)
    
    for t in cases[-2:]:
        print(t)
        print(digit_length_correct(t))
        print(digit_length_clever_2(t))
◧◩◪
3. contra+r01[view] [source] 2019-11-11 12:34:26
>>gspetr+qv
Using arbitrary precision arithmetic kind of defeats the point of not using loops.
[go to top]