简体   繁体   中英

Numerical differentiation with python

I have such a task:

You need to write a function with the following signature: def derForward(f, I, h) This function should get as input function and segment as Python list of two elements --- ends of the segment. In the function you are asked to divide the segment into small segments of length ℎ, thus getting a grid. Your function should return dy --- forward differences for each point x (except the border since the formula asks for the next value). You should return both x and dy arrays of the same length.

My answer looks this way:

xx = [] #list of x values
frw = [] #list of forw. differencies of x

def derForward(f, I, h):
    x = np.arange(I[0], I[1], h)
    f = np.vectorize(f)
    for x_ in x[:-1]:
        dxdy = (f(x_+h)-f(x_))/ h
        xx.append(x_)
        frw.append(dxdy)
    x = np.array(xx)
    dy = np.array(frw)
    return x, dy

This function has to pass 3 tests for errors and accuracy. But now it is failing with tests 2 and 3. And I don't understand why I can pass only 1 test. The checker looks like this:

import numpy as np
from math import *


from time import time

def findif_check(derForward):
    count=0
    I=[0.001, 2*np.pi]
    f=lambda x: sin(x)
    h=0.01
    st=time()
    x, dy=derForward(f, I, h)
    dur=time()-st

    if x.shape[0]!=dy.shape[0]:
        print('FAILED: x and dy shape mismatch!')
    else:
        df=lambda x: cos(x)    
        err=np.max(np.abs(dy-np.vectorize(df)(x)))
        print('Test 1 |::|  err=', np.max(np.abs(dy-np.cos(x))), '  |::|  time: ', dur, 's')
        if err<2*0.0075:
            count+=1
            print('Test 1 |::|  accuracy OK') 
        else:
            print('Test 1 |::|  accuracy FAIL') 
        f=lambda x: x**x
        I=[0.001, 1]

        st=time()
        x, dy=derForward(f, I, h)
        dur=time()-st
        
        df=lambda x: x**x*(log(x)+1)
        err=np.max(np.abs(dy-np.vectorize(df)(x)))
        print('Test 2 |::|  err=', err, '  |::|  time: ', dur, 's')
        if err<2:
            count+=1
            print('Test 2 |::|  accuracy OK')
        else:
            print('Test 2 |::|  accuracy FAIL')

        f=lambda x: e**(-x**2)
        I=[0.001, 1]

        st=time()
        x, dy=derForward(f, I, h)
        dur=time()-st
        
        df=lambda x: -2*x*e**(-x**2)
        err=np.max(np.abs(dy-np.vectorize(df)(x)))
        print('Test 3 |::|  err=', err, '  |::|  time: ', dur, 's')
        if err<2*0.01:
            count+=1
            print('Test 3 |::|  accuracy OK')
        else:
            print('Test 3 |::|  accuracy FAIL')
    print('Passed: ', count, '/ 3')
   

Because when the test 2 and 3 is running, variable xx and frw contains data of test 1.

So move the definition of xx and frw into def derForward(f, I, h): as below:

def derForward(f, I, h):
    xx = [] #list of x values
    frw = [] #list of forw. differencies of x

    x = np.arange(I[0], I[1], h)
    f = np.vectorize(f)
    // ... ... ... ...

Then all 3 tests passed:

Test 1 |::|  err= 0.004999976659897233   |::|  time:  0.04198646545410156 s
Test 1 |::|  accuracy OK
Test 2 |::|  err= 1.715675908387758   |::|  time:  0.007221221923828125 s
Test 2 |::|  accuracy OK
Test 3 |::|  err= 0.009999270029526776   |::|  time:  0.00669407844543457 s
Test 3 |::|  accuracy OK
Passed:  3 / 3

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM