Montecarlo Kotlin

This commit is contained in:
Parric007
2024-05-13 12:08:29 +02:00
commit b5ed399b0c
11 changed files with 251 additions and 0 deletions

131
src/Main.kt Normal file
View File

@@ -0,0 +1,131 @@
import java.text.DecimalFormat
import kotlin.math.abs
import kotlin.math.pow
import kotlin.random.Random.Default.nextDouble
import kotlin.system.measureTimeMillis
var lowerX = 0.0
var upperX = 20.0
fun randomFloat(): Double {
return nextDouble()
}
class Point(private var x: Double, private var y: Double) {
fun getX() : Double {
return x
}
fun getY() : Double {
return y
}
}
class LinearBounds(private var lower: Float, private var higher: Float) {
fun length(): Double {
return abs(higher-lower).toDouble()
}
fun getRandomValue() : Double{
return lower + (randomFloat()*length())
}
fun getLower() : Float {
return lower
}
fun getHigher() : Float {
return higher
}
}
class Bounds(private var x : LinearBounds, private var y : LinearBounds) {
fun area() : Double {
return x.length() * y.length()
}
fun getRandomPoint() : Point {
return Point(x.getRandomValue(), y.getRandomValue())
}
fun getX() : LinearBounds {
return x
}
}
fun function(x : Double) : Double {
return x.pow(4.0) -4* x.pow(3.0) +18* x.pow(2.0) -12*x-69
}
fun indefiniteIntegral(x : Double) : Double {
return (1.0/5) * x.pow(5) - x.pow(4) + 6*x.pow(3) - 6 * x.pow(2) -69*x
}
fun getIsInside(p : Point) : Boolean {
var y0 = function(p.getX())
return abs(y0) > abs(p.getY()) && y0*p.getY() >= 0
}
fun getRealIntegral(bounds : LinearBounds) : Double{
return indefiniteIntegral(bounds.getHigher()-indefiniteIntegral(bounds.getLower().toDouble()))
}
fun getUpperLimit() : Float{
var upperLimit = 0.0f
var i = lowerX
while(i < upperX) {
i += 0.025
if(function(i) > upperLimit) {
upperLimit = (function(i) * 1.025).toFloat()
}
}
return upperLimit
}
fun getLowerLimit() : Float {
var lowerLimit = 0.0f
var i = lowerX
while(i < upperX) {
i += 0.025
if(function(i) < lowerLimit) {
lowerLimit = (function(i) * 1.025).toFloat()
}
}
return lowerLimit
}
fun main() {
val format = DecimalFormat("#,###.##")
var pointsInside = 0.0
val samples = 20_000_000
val bounds = Bounds(LinearBounds(lowerX.toFloat(), upperX.toFloat()), LinearBounds(getLowerLimit(), getUpperLimit()))
var integral = 0.0
var error = 0.0
var result = 0.0
val realValue = getRealIntegral(bounds.getX())
var toTestPoint : Point
val elapsed = measureTimeMillis {
for(i in 0..50){
for(ii in 0..samples) {
toTestPoint = bounds.getRandomPoint()
if(getIsInside(toTestPoint)){
pointsInside++
}
}
integral = (pointsInside/samples) * bounds.area()
result += integral
integral = 0.0
pointsInside = 0.0
}
result /= 50.0
error = abs(realValue-result)
}
println("The approximated Integral of the function is: " + format.format(result))
println("The real Integral of the function is: " + format.format(realValue))
println("That's an error of " + format.format(error) + " or " + format.format((error/realValue)*100) + "%")
println("And the whole thing took " + format.format(elapsed/1000.0) + " Seconds for 50 times" + format.format(samples) + " Samples")
}