0

问题如下我有一个大或小数字(可以是一个),我需要调整这个数字并通过计算。鉴于计算的结果,它必须至少在小数点后 5 位上达到某个值。

所以我需要制作一个采用这个起始值的方法,根据当前结果尝试增加或减少它,直到我得到正确的结果。我做了一些尝试,但没有成功。

这是一个根本不起作用的例子,但它暗示了我的意思......(这只是一个小规模的测试用例)

   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);         
}

示例 2 可能是一个更清晰的描述。这是我现在的解决方案..

guessingValue = firstImput;

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

}

4

4 回答 4

1

一种方法是将您的问题定义为本地优化任务并使用本地优化器(例如 Brent 的方法或来自Apache commons的 Nelder Mead Simplex )。

您的目标函数将是所需值与您从黑匣子中获得的值之间的距离。

于 2013-10-29T12:43:48.573 回答
1

正如我在上面的评论中已经提到的,您不应该使用内置运算符比较双精度数。这是您的代码无法正常工作的主要原因。第二个是 else 子句中的 tmpPay = tmpPay + ((top-low) /2); 而不是 tmpPay = tmpPay - ((top-low) /2 );

完整的固定代码如下:

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);




    }
}
于 2013-10-29T13:32:54.823 回答
1

如果我理解正确,你有一个函数 g(x) 和一个值 K,你想找到 x0 使得 g(x0) = K。这相当于找到函数 f(x) = g(x ) - K,因为 f(x0) == f(x0) - K == K - K == 0。

一个简单的算法是牛顿法

于 2013-10-29T12:45:50.410 回答
1

如果试图运行程序,它很容易陷入无限循环,因为 while 条件(用于双值比较)几乎不可能相等。例如,有 2 个值如下:

双值1 = 3666.545

双值2 = 3666.54500001

value1 == value2 是假的。

即使是这种价值观也不是平等的。

你最好定义一个偏差范围。

例如,如果 |value1 - value2| < 0.005,然后打破while条件并打印随机num信息。

于 2013-10-29T13:00:22.120 回答