0

The problem is as follows i have a large or small number (can be either one) and i need to tweak this number and put it through a caluclation. Given the result of the calulation it has to mach a certain value on the 5th decimal at least.

So i need to make a method that takes this starting value, tries to increase or decrease it given what the current result is until i get the correct result. I have made some atempts with no success.

Here is an example that won't woork at all but it hints towards what i mean... (this is just a small scale test case)

   public class Test {
        public static void main(String[]args)
        {
            double ran = 100 + (int)(Math.random() * 100000.999999999);
            int count = 0;              
            double tmpPay = 3666.545;
            double top = tmpPay;
            double low = 0;             

            while ( tmpPay != ran )
            {
                if ( tmpPay > ran)
                {
                    if( low == 0)
                    {
                            tmpPay = top / 2;
                            top = tmpPay;
                    }
                    else
                    {
                        tmpPay = tmpPay + ((top - low) / 2);
                        top = tmpPay;
                    }        
                }           

                if (tmpPay  < ran)
                {
                    tmpPay = top * 1.5;
                    low = top;
                    top = tmpPay;                   
                }
            }
            System.out.println(" VAlue of RAN: " +ran + "----VALUE OF tmpPay: " + tmpPay + "---------- COUNTER: " + count);         
}

Example 2 mabey a more clear description. This is my solution now..

guessingValue = firstImput;

while (amortization > tmpPV)
{
    guessingValue -= (decimal)1;
    //guessingVlue -- > blackbox
    amortization = blackboxResults;
}
 while (amortization < tmpPV)
{
    guessingValue += (decimal)0.00001;
    //guessingVlue -- > blackbox
    amortization = blackboxResults;
}

}

SomeRandomName
  • 593
  • 1
  • 8
  • 23
  • `c#` and `java`? You should pick one. – Soner Gönül Oct 29 '13 at 12:26
  • Are you trying to do a binary search? – Eamonn McEvoy Oct 29 '13 at 12:28
  • Not really a binary search. I need to find what the in parameter should be for a calculation to get a specific answer. Think of the calculation itself as a black box. – SomeRandomName Oct 29 '13 at 12:30
  • Comparing doubles using standard java operators ==,<,> etc. is not a good idea. You can find why here http://stackoverflow.com/questions/3832592/test-for-floating-point-equality-fe-floating-point-equality – Luke Oct 29 '13 at 12:32
  • If the calculation is truly a black box, it's impossible - consider `if (x == 0.3433) return 1; else return 0;`. It's impossible to know when the function would return `1` here. – Bernhard Barker Oct 29 '13 at 12:36
  • If trying to run the program, it will easily be in infinite loop, since the while condition could hardly equal by double values comparison. e.g. There are 2 values, double value1 = 3666.545; double value2 = 3666.545002; value1 == value2 is false. Even this kind of values are not equal. You'd better define a range for deviation. Then, e.g, if |value1 - value2| <0.0002, then break the while condition and print the random num information. – Mengjun Oct 29 '13 at 12:48
  • Thanks for the tip of the range. – SomeRandomName Oct 29 '13 at 13:17

4 Answers4

1

One way would be to define your problem as a local optimization task and use an local optimizer (for example Brent's method or Nelder Mead Simplex from Apache commons).

Your goal function here would be the distance between the desired value and what you get from your black box.

dratewka
  • 2,104
  • 14
  • 15
  • Mabey that is a solution i can try and specify my problem even further and add another example in the question. ANd if this applies could u hint at how to implement this? – SomeRandomName Oct 29 '13 at 13:18
1

If I understand correctly, you have a function g(x) and a value K, you want to find x0 such that g(x0) = K. This is equivalent to find the roots of the function f(x) = g(x) - K, because f(x0) == f(x0) - K == K - K == 0.

A simple algorithm would be Newton's method.

Marco Pantaleoni
  • 2,529
  • 15
  • 14
1

If trying to run the program, it will easily be in infinite loop, since the while condition (for double values comparison) could hardly equal. e.g. There are 2 values as follows:

double value1 = 3666.545;

double value2 = 3666.54500001;

value1 == value2 is false.

Even this kind of values are not equal.

You'd better define a range for deviation.

e.g, if |value1 - value2| < 0.005, then break the while condition and print the random num information.

Mengjun
  • 3,159
  • 1
  • 15
  • 21
1

As I already mentioned in the comment above you should not compare doubles using build-in operators. This is the main reason why your code is not working. The second one is that in else clause tmpPay = tmpPay + ((top-low) /2); instead of tmpPay = tmpPay - ((top-low) /2 );

Complete fixed code is below :

public class Test {
    private static final double EPSILON = 0.00001;
    public static boolean isEqual( double a, double b){

        return (Math.abs(a - b) < EPSILON);

    }


    public static void main(String[]args)
    {

        double ran = 100 + (int)(Math.random() * 100000.999999999);
        int count = 0;              
        double tmpPay = 3666.545;
        double top = tmpPay;
        double low = 0;             

        while ( !isEqual(tmpPay, ran))
        {
            if ( tmpPay > ran)
            {
                if( isEqual(low, 0.0))
                {
                        tmpPay = top / 2;
                        top = tmpPay;
                }
                else
                {
                    tmpPay = tmpPay - ((top - low) / 2);
                    top = tmpPay;
                }        
            }           

            if (tmpPay  < ran)
            {
                tmpPay = top * 1.5;
                low = top;
                top = tmpPay;                   
            }
            System.out.println("RAN:"+ran+" tmpPay:"+tmpPay+" top:"+top+" low:"+low+" counter:"+count);
            count++;
        }
        System.out.println(" VAlue of RAN: " +ran + "----VALUE OF tmpPay: " + tmpPay + "---------- COUNTER: " + count);




    }
}
Luke
  • 1,236
  • 2
  • 11
  • 16