summaryrefslogtreecommitdiffstats
path: root/DataStructure/NormDistribution.java
blob: 109d4faacd9be098b398bda2e7df1a4f0f298352 (plain) (blame)
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
package DataStructure;

class NormDistribution {
	double variance;
	double mean;
	static final double sqrtPI = 2.506628274631000502415765284811d;

	public static void main(String args[]) {
		NormDistribution one = new NormDistribution(5.12, 10);
		NormDistribution two = new NormDistribution(5.12, 10);
		NormDistribution three = new NormDistribution(0, 4);
		System.out.println(one.intersection(two));
		System.out.println("value at max: " + three.valueAt(2));
	}

	public NormDistribution(double mean, double variance) {
		this.mean = mean;
		this.variance = variance;
	}

	public double valueAt(double x) {
		double std = Math.sqrt(variance);
		// double sqrtPI = Math.sqrt(2 * Math.PI);

		double exp = Math.exp(((Math.pow((x - mean), 2)) / variance) / (-2));
		double result = (1 / (std * sqrtPI)) * exp;
		return result;
	}

	/**
	 * Calculates the intersection area of both Distributions
	 * 
	 * @param distribution
	 * @return
	 */
	public double intersection(NormDistribution distribution) {

		// return one, if both distributions are alike? (speedup)
		if (Math.abs(this.mean - distribution.mean) < 0.01
				&& Math.abs(this.variance - distribution.variance) < 0.01) {
			return 0.998;
		}

		// if (variance < 0.1 && distribution.variance < 0.1
		// && Math.abs(mean - distribution.mean) < 0.1) {
		// return 1;
		// }

		// get plus/minus 3*sigma Intervall (95% of the values)
		double begin = -3.5
				* Math.sqrt(Math.min(variance, distribution.variance))
				+ Math.min(mean, distribution.mean);
		;
		double end = 3.5 * Math.sqrt(Math.max(variance, distribution.variance))
				+ Math.max(mean, distribution.mean);
		// get stepwidth for integration.
		double step = (end - begin) / 42; // Resolution: 42 steps!
		// what if rounding errors appear and step == 0?
		if (step < 0.0000001) {
			return 0;
		}

		double area = 0;
		end -= step;

		for (double x0 = begin; x0 <= end; x0 += step) {
			// get min value
			double x1 = x0 + step;
			double fx0 = Math.min(valueAt(x0), distribution.valueAt(x0));
			double fx1 = Math.min(valueAt(x1), distribution.valueAt(x1));
			area += fx0 * (x1 - x0) + ((x1 - x0) * (fx1 - fx0)) / 2;
		}

		return area;
	}

}