From 5a9440dd17221ded73d11d01241865301eeb0214 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Sun, 21 Jul 2024 18:55:12 +0200 Subject: [PATCH] fix(evaluator): Improve sin and cos threshold values Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com> --- .../sadellie/evaluatto/BigDecimalMath.kt | 21 +++++++++++++++++-- .../github/sadellie/evaluatto/Expression.kt | 7 ++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/BigDecimalMath.kt b/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/BigDecimalMath.kt index ad35f5cb..cda7b230 100644 --- a/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/BigDecimalMath.kt +++ b/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/BigDecimalMath.kt @@ -26,9 +26,19 @@ import kotlin.math.asin import kotlin.math.atan import kotlin.math.pow +// Dirty hack to avoid -0.000000000001 +val PI_THRESHOLD = BigDecimal("0.000000000000001") + internal fun BigDecimal.sin(radianMode: Boolean): BigDecimal { val angle: Double = if (radianMode) this.toDouble() else Math.toRadians(this.toDouble()) - return kotlin.math.sin(angle).toBigDecimal() + + val result = kotlin.math.sin(angle).toBigDecimal() + + if (result.abs() < PI_THRESHOLD) { + return BigDecimal.ZERO + } + + return result } internal fun BigDecimal.arsin(radianMode: Boolean): BigDecimal { @@ -38,7 +48,14 @@ internal fun BigDecimal.arsin(radianMode: Boolean): BigDecimal { internal fun BigDecimal.cos(radianMode: Boolean): BigDecimal { val angle: Double = if (radianMode) this.toDouble() else Math.toRadians(this.toDouble()) - return kotlin.math.cos(angle).toBigDecimal() + + val result = kotlin.math.cos(angle).toBigDecimal() + + if (result.abs() < PI_THRESHOLD) { + return BigDecimal.ZERO + } + + return result } internal fun BigDecimal.arcos(radianMode: Boolean): BigDecimal { diff --git a/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/Expression.kt b/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/Expression.kt index f0a648ca..39197b5b 100644 --- a/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/Expression.kt +++ b/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/Expression.kt @@ -93,6 +93,10 @@ class Expression( } moveIfMatched(Token.Operator.divide) -> { + // Adding those `setScale` calls have been added in + // 36a931c7d175b5cad52ff3abceb7784b0bb82aac to fix #18 + // I'm not sure if this is the correct way to fix it, but it + // seems to be working val divisor = parseFactor().setScale(MAX_PRECISION) if (divisor.compareTo(BigDecimal.ZERO) == 0) throw ExpressionException.DivideByZero() @@ -166,7 +170,8 @@ class Expression( // sin if (moveIfMatched(Token.Func.sin)) { - expr = parseFuncParentheses().sin(radianMode) + val x = parseFuncParentheses() + expr = x.sin(radianMode) } // cos