mathpython-2.xfrequencymidi

math.log() results in "ValueError: math domain error"


This is a frequency to MIDI note converter, but I can't seem to get the math to work properly. Specifically, with the math.log() function. This will produce an output of 69.0 most of the time, but it usually outputs "ValueError: math domain error", if I input any number below 440. How should I fix it?

    #d=69+12*log(2)*(f/440)
    #f=2^((d-69)/12)*440
    #d is midi, f is frequency

    import math
    f=raw_input("Type the frequency to be converted to midi: ")
    d=69+(12*math.log(int(f)/440))/(math.log(2))
    print d`

Solution

  • This is because Python 2 uses integer division. Anything below 440 will evaluate to 0 which is then passed to math.log().

    >>> 500/440
    1
    >>> 440/440
    1
    >>> 439/440
    0
    >>> math.log(0)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: math domain error
    

    The easiest way is to enable Python 3 style so called true division by placing this line at the top of your file:

    from __future__ import division
    

    Now Python 2 will behave as you might have expected:

    >>> 439/440
    0.9977272727272727
    >>> math.log(439/440)
    >>> math.log(439/440)
    -0.0022753138371355394
    

    As alternatives, you can convert the dividend and/or divisor to a float:

    d=69+(12*math.log(int(f)/440.0))/(math.log(2))
    

    or

    d=69+(12*math.log(float(f)/440))/(math.log(2))