-
Notifications
You must be signed in to change notification settings - Fork 1
/
GoalSeekFunction.java
162 lines (142 loc) · 4.61 KB
/
GoalSeekFunction.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package com.zuci.dashboard;
import java.text.DecimalFormat;
/**
* The type Goal seek function.
*/
public class GoalSeekFunction {
/**
* The constant ITERATOR_LIMIT.
*/
private static final int ITERATOR_LIMIT = 10000000;
/**
* The constant THRESHOLD.
*/
private static final double THRESHOLD = 0.000_000_000_1;
/**
* The interface Compute interface.
* use this to implement the required computation logic
*/
public interface ComputeInterface {
/**
* Compute double.
*
* @param currentValue the current value
* @return the double
*/
double compute(double currentValue);
}
/**
* Gets goal seek.
*
* @param goalSeek the goal seek
* @param computeInterface the compute interface
* @return the goal seek
*/
public Double getGoalSeek(final GoalSeek goalSeek, final ComputeInterface computeInterface) {
int iterator = 1; /* how many times bisection has been performed */
double currentValue;
do {
currentValue = computeInterface.compute(goalSeek.getMidValue() / 100); // passing as percent
if (!Double.isInfinite(currentValue) && !Double.isNaN(currentValue)) {
// evaluate function at midpoint & determine next interval bound
goalSeek.checkCurrentValue(currentValue);
if (goalSeek.getDifference(currentValue) == 0d)
return goalSeek.getMidValue();
}
iterator++; // increment iteration
} while (Math.abs(goalSeek.getMinimumBoundaryValue() - goalSeek.getMaximumBoundaryValue()) / 2 >= THRESHOLD && Math.abs(goalSeek.getDifference(currentValue)) > THRESHOLD && iterator <= ITERATOR_LIMIT);
throw new RuntimeException("Goal not found");
}
/**
* The entry point of application.
*
* @param arguments the input arguments
*/
public static void main(String[] arguments) {
//testGetGoalSeek()
final GoalSeekFunction goalSeekFunction = new GoalSeekFunction();
final Double goalSeek = goalSeekFunction.getGoalSeek(new GoalSeek(27000, 0, 100), a -> a * 100000);
System.out.println(goalSeek);
}
}
/**
* The type Goal seek.
*/
class GoalSeek {
/**
* The Decimal format.
*/
private final DecimalFormat decimalFormat = new DecimalFormat("#0.000000");
/**
* The Target value.
*/
private final double targetValue;
/**
* The Minimum boundary value.
*/
private double minimumBoundaryValue;
/**
* The Maximum boundary value.
*/
private double maximumBoundaryValue;
/**
* Instantiates a new Goal seek.
*
* @param targetValue the target value
* @param minimumBoundaryValue the minimum boundary value
* @param maximumBoundaryValue the maximum boundary value
*/
public GoalSeek(final double targetValue, final double minimumBoundaryValue, final double maximumBoundaryValue) {
this.targetValue = targetValue;
this.minimumBoundaryValue = minimumBoundaryValue;
this.maximumBoundaryValue = maximumBoundaryValue;
}
/**
* Gets mid value.
*
* @return the mid value
*/
// bisection gives us the "average" of the point values
public double getMidValue() {
return (minimumBoundaryValue + maximumBoundaryValue) / 2;
}
/**
* Check current value.
*
* @param currentValue the current value
*/
public void checkCurrentValue(final double currentValue) {
final double difference = getDifference(currentValue);
final double midValue = getMidValue();
if (difference < 0) {
maximumBoundaryValue = midValue;
} else {
minimumBoundaryValue = midValue;
}
}
/**
* Gets difference.
*
* @param currentValue the current value
* @return the difference
*/
public double getDifference(final double currentValue) {
return Double.parseDouble(decimalFormat.format(targetValue - currentValue));
}
/**
* Gets minimum boundary value.
*
* @return the minimum boundary value
*/
public double getMinimumBoundaryValue() {
return minimumBoundaryValue;
}
/**
* Gets maximum boundary value.
*
* @return the maximum boundary value
*/
public double getMaximumBoundaryValue() {
return maximumBoundaryValue;
}
}