Skip to content

Commit

Permalink
Merge pull request #1 from ali-zareshai/fix_bug_big_number
Browse files Browse the repository at this point in the history
Fix bug big number
  • Loading branch information
abbasalim authored Mar 25, 2023
2 parents f1cf00f + 2a08631 commit f01724a
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 17 deletions.
3 changes: 3 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ android {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
}
testOptions {
unitTests.returnDefaultValues = true
}
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,56 @@
package com.gnacoding.composecalculator

import ir.wave.composecalculator.CalculatorViewModel
import org.junit.Test

import org.junit.Assert.*
import org.junit.Before
import java.math.BigDecimal
import java.math.BigInteger
import java.math.RoundingMode

/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
private lateinit var calculatorViewModel:CalculatorViewModel

@Before
fun setup(){
calculatorViewModel = CalculatorViewModel()
}

@Test
fun multiplyTwoBigInt(){
assertEquals(BigDecimal("6000000000000000000896000000000000000.032768"),calculatorViewModel.calculate("3000000000000000000.256×2000000000000000000.128"))
}

@Test
fun sumTwoInt(){
assertEquals((256).toBigDecimal(),calculatorViewModel.calculate("128+128"))
}

@Test
fun sumTwoBigInt(){
assertEquals(BigDecimal("5000000000000000000.384"),calculatorViewModel.calculate("3000000000000000000.256+2000000000000000000.128"))
}

@Test
fun multiplyTwoInt(){
assertEquals(BigDecimal("16384"),calculatorViewModel.calculate("128×128"))
assertEquals(BigDecimal("16422.42"),calculatorViewModel.calculate("128.1×128.2"))
assertEquals(BigDecimal("16422.4200"),calculatorViewModel.calculate("128.10×128.20"))
assertEquals(BigDecimal("16384.00"),calculatorViewModel.calculate("128.0×128.0"))
assertEquals(BigDecimal("16384.0000000"),calculatorViewModel.calculate("128.000×128.0000"))
}

@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
fun divTwoInt(){
assertEquals(BigDecimal("0.3333"),calculatorViewModel.calculate("1÷3"))
assertEquals(BigDecimal("0.3333"),calculatorViewModel.calculate("1.0÷3"))
assertEquals(BigDecimal("0.3333"),calculatorViewModel.calculate("1.0÷3.0"))
assertEquals(BigDecimal("0.3333"),calculatorViewModel.calculate("1÷3.0"))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import ir.wave.composecalculator.Utils.CalculatorAction
import ir.wave.composecalculator.Utils.CalculatorOperation
import java.math.BigDecimal
import java.math.RoundingMode
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
import java.util.*

class CalculatorViewModel ( ): ViewModel( ) {

var state by mutableStateOf(CalculatorState())
set
set

var onResult: (String)->Unit ={}
var roundResult: Boolean=false
Expand Down Expand Up @@ -120,9 +122,9 @@ class CalculatorViewModel ( ): ViewModel( ) {
}


fun calculate(str: String): Double {
fun calculate(str: String): BigDecimal {
Log.d("Calculator", str);
return if (str.trim { it <= ' ' }.length == 0) 0.toDouble() else object : Any() {
return if (str.trim { it <= ' ' }.length == 0) 0.toBigDecimal() else object : Any() {
var pos = -1
var ch = 0
fun nextChar() {
Expand All @@ -138,7 +140,7 @@ class CalculatorViewModel ( ): ViewModel( ) {
return false
}

fun parse(): Double {
fun parse(): BigDecimal {
nextChar()
val x = parseExpression()
if (pos < str.length) {
Expand All @@ -152,7 +154,7 @@ class CalculatorViewModel ( ): ViewModel( ) {
// term = factor | term `×` factor | term `÷` factor
// factor = `+` factor | `−` factor | `(` expression `)`
// | number | functionName factor | factor `^` factor
fun parseExpression(): Double {
fun parseExpression(): BigDecimal {
var x = parseTerm()
while (true) {
if (eat('+'.code)) x += parseTerm() // addition
Expand All @@ -161,41 +163,41 @@ class CalculatorViewModel ( ): ViewModel( ) {
}
}

fun parseTerm(): Double {
fun parseTerm(): BigDecimal {
var x = parseFactor()
while (true) {
if (eat('×'.code)) x *= parseFactor() // multiplication
else if (eat('÷'.code)) x /= parseFactor() // division
else if (eat('÷'.code)) x = x.divide(parseFactor(),4, RoundingMode.HALF_EVEN) // division
else return x
}
}

fun parseFactor(): Double {
fun parseFactor(): BigDecimal {
if (eat('+'.code)) return parseFactor() // unary plus
if (eat(''.code) || eat('-'.code)) return -parseFactor() // unary minus
var x: Double
var x: BigDecimal
val startPos = pos
if (eat('('.code)) { // parentheses
x = parseExpression()
eat(')'.code)
} else if (ch >= '0'.code && ch <= '9'.code || ch == '.'.code) { // numbers
while (ch >= '0'.code && ch <= '9'.code || ch == '.'.code) nextChar()
x = str.substring(startPos, pos).toDouble()
x = str.substring(startPos, pos).toBigDecimal()
} else if (ch >= 'a'.code && ch <= 'z'.code) { // functions
while (ch >= 'a'.code && ch <= 'z'.code) nextChar()
val func = str.substring(startPos, pos)
x = parseFactor()
x = when (func) {
"sqrt" -> Math.sqrt(x)
"sin" -> Math.sin(Math.toRadians(x))
"cos" -> Math.cos(Math.toRadians(x))
"tan" -> Math.tan(Math.toRadians(x))
"sqrt" -> Math.sqrt(x.toDouble()).toBigDecimal()
"sin" -> Math.sin(Math.toRadians(x.toDouble())).toBigDecimal()
"cos" -> Math.cos(Math.toRadians(x.toDouble())).toBigDecimal()
"tan" -> Math.tan(Math.toRadians(x.toDouble())).toBigDecimal()
else -> throw RuntimeException("Unknown function: $func")
}
} else {
throw RuntimeException("Unexpected: " + ch.toChar())
}
if (eat('^'.code)) x = Math.pow(x, parseFactor()) // exponentiation
if (eat('^'.code)) x = Math.pow(x.toDouble(), parseFactor().toDouble()).toBigDecimal() // exponentiation
return x
}
}.parse()
Expand Down

0 comments on commit f01724a

Please sign in to comment.