Montecarlo Kotlin
This commit is contained in:
131
src/Main.kt
Normal file
131
src/Main.kt
Normal 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")
|
||||
}
|
||||
Reference in New Issue
Block a user