There is a book that answers this question (and others like it):
Numerical recipes in C, 2nd Edition, Press, Vetterling, Teukolsky and Flannery. This book also comes in versions of C ++, Fortran, and BASIC. Unfortunately, no version of Java exists. In addition, I believe that this book is not printed, but you can buy used versions of some of them on the Internet (at least through bn.com.)
Section 5.7, “Numerical Derivatives,” p. 186 accurately explains the problem you see with numerical derivatives, and the math behind why this happens, and also the function to calculate the correct numerical derivative (in C, but it’s easy to translate it to Java). Here is a summary of their simple approximation:
1) Numerically you better calculate the symmetric version:
f '(x) = (f (x + h) - f (x - h)) / 2h
2) h should be approximately (sigma_f) ^ (1/3) * x_c
Where
sigma_f = ~ fractional accuracy of the calculation of the function f (x) for simple functions
x_c = ~ x if x is not equal to zero.
However, this does not lead to optimal derivatives, since the error is ~ (sigma_f) ^ (2/3). The best solution is the Ridders algorithm, which is presented as program C in the book (Ridders reference, CJF 1982, Advances in Engineering Software, Volume 4, No. 2, pp. 75-76.)