How to Create Simple Calculator in Android Studio Kotlin
In this Tutorial we will learn how to create a simple calculator in android studio.Lets start
Step 1: Building the user interface
First we design our user interface using TextView, Button and ImageButton. TextView are used to display user input and result, Button and ImageButton are Used to get user Input.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="15dp"
android:weightSum="3"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:layout_weight="1">
<TextView
android:id="@+id/display"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="5dp"
android:gravity="end|bottom"
android:hint="0"
android:textSize="36dp"
android:fontFamily="sans-serif-black"
android:maxLines="4"
android:textColor="@android:color/black"
android:background="@android:color/transparent" />
<TextView
android:id="@+id/result"
android:layout_width="match_parent"
android:layout_height="0dp"
android:visibility="gone"
android:layout_weight=".5"
android:padding="5dp"
android:gravity="end|bottom"
android:text="="
android:textSize="26dp"
android:fontFamily="sans-serif-black"
android:maxLines="4"
android:textColor="@android:color/black"
android:background="@android:color/transparent" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@android:color/black"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:weightSum="5"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
android:weightSum="4">
<Button
android:id="@+id/button_clear"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="C"
android:textSize="26dp"
android:textColor="@color/colorAccent"
android:fontFamily="sans-serif-black"
android:background="@drawable/ripple_bg"/>
<Button
android:id="@+id/button_modulas"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="%"
android:textSize="26dp"
android:textColor="@color/colorAccent"
android:fontFamily="sans-serif-black"
android:background="@drawable/ripple_bg"/>
<Button
android:id="@+id/button_div"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="÷"
android:textSize="26dp"
android:textColor="@color/colorAccent"
android:fontFamily="sans-serif-black"
android:background="@drawable/ripple_bg"/>
<Button
android:id="@+id/button_multi"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="×"
android:textSize="26dp"
android:textColor="@color/colorAccent"
android:fontFamily="sans-serif-black"
android:background="@drawable/ripple_bg"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
android:weightSum="4">
<Button
android:id="@+id/button_7"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="7"
android:textSize="26dp"
android:fontFamily="sans-serif-black"
android:background="@drawable/ripple_btn"/>
<Button
android:id="@+id/button_8"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="8"
android:textSize="26dp"
android:fontFamily="sans-serif-black"
android:background="@drawable/ripple_btn"/>
<Button
android:id="@+id/button_9"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="9"
android:textSize="26dp"
android:fontFamily="sans-serif-black"
android:background="@drawable/ripple_btn"/>
<Button
android:id="@+id/button_sub"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="-"
android:textSize="26dp"
android:textColor="@color/colorAccent"
android:fontFamily="sans-serif-black"
android:background="@drawable/ripple_bg"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
android:weightSum="4">
<Button
android:id="@+id/button_4"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="4"
android:textSize="26dp"
android:fontFamily="sans-serif-black"
android:background="@drawable/ripple_btn"/>
<Button
android:id="@+id/button_5"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="5"
android:textSize="26dp"
android:fontFamily="sans-serif-black"
android:background="@drawable/ripple_btn"/>
<Button
android:id="@+id/button_6"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="6"
android:textSize="26dp"
android:fontFamily="sans-serif-black"
android:background="@drawable/ripple_btn"/>
<Button
android:id="@+id/button_add"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="+"
android:textSize="26dp"
android:textColor="@color/colorAccent"
android:fontFamily="sans-serif-black"
android:background="@drawable/ripple_bg"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:orientation="horizontal"
android:weightSum="4">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_weight="3"
android:weightSum="2">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
android:weightSum="3">
<Button
android:id="@+id/button_3"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="3"
android:textSize="26dp"
android:fontFamily="sans-serif-black"
android:background="@drawable/ripple_btn"/>
<Button
android:id="@+id/button_2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="2"
android:textSize="26dp"
android:fontFamily="sans-serif-black"
android:background="@drawable/ripple_btn"/>
<Button
android:id="@+id/button_1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="1"
android:textSize="26dp"
android:fontFamily="sans-serif-black"
android:background="@drawable/ripple_btn"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
android:weightSum="3">
<ImageButton
android:id="@+id/button_back"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:src="@drawable/back"
android:backgroundTint="@color/colorAccent"
android:background="@drawable/ripple_bg"/>
<Button
android:id="@+id/button_0"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="0"
android:textSize="26dp"
android:fontFamily="sans-serif-black"
android:background="@drawable/ripple_btn"/>
<Button
android:id="@+id/button_dot"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="."
android:textSize="26dp"
android:fontFamily="sans-serif-black"
android:background="@drawable/ripple_btn"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<Button
android:id="@+id/button_equal"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="="
android:textSize="40dp"
android:textColor="@android:color/white"
android:fontFamily="sans-serif-black"
android:background="@drawable/ripple_equal_btn"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
Step 2: Setup Resource file
1. Right click on drawable -> new -> Image Asset Choose Icon Type Action Bar and Tab Icons then click Click Art Image and select Which Icon Name is close then press ok and then name it back and change color and use this color code D81B60 finaly click next->Finish.
2. Right click on drawable -> new -> Drawable Resource File then name it ripple_bg and click Ok. You can see ripple_bg.xml file under your drawable folder. Copy the bellow code and paste it into your ripple_bg.xml.
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:color="@color/colorPrimaryDark"
tools:targetApi="lollipop">
<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<solid android:color="@color/colorPrimaryDark" />
<corners android:radius="0dp" />
</shape>
</item>
<item android:id="@android:id/background">
<shape android:shape="rectangle">
<gradient
android:angle="90"
android:endColor="@android:color/transparent"
android:startColor="@android:color/transparent"
android:type="linear" />
<corners android:radius="0dp" />
</shape>
</item>
</ripple>
3. Right click on drawable -> new -> Drawable Resource File then name it ripple_bg and click Ok. You can see ripple_btn.xml file under your drawable folder. Copy the bellow code and paste it into your ripple_btn.xml.
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:color="#88000000"
tools:targetApi="lollipop">
<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<solid android:color="#88000000" />
<corners android:radius="0dp" />
</shape>
</item>
<item android:id="@android:id/background">
<shape android:shape="rectangle">
<gradient
android:angle="90"
android:endColor="@android:color/transparent"
android:startColor="@android:color/transparent"
android:type="linear" />
<corners android:radius="0dp" />
</shape>
</item>
</ripple>
4. Right click on drawable -> new -> Drawable Resource File then name it ripple_bg and click Ok. You can see ripple_equal_btn.xml file under your drawable folder. Copy the bellow code and paste it into your ripple_equal_btn.xml.
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:color="#000000"
tools:targetApi="lollipop">
<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<solid android:color="#000000" />
<corners android:radius="0dp" />
</shape>
</item>
<item android:id="@android:id/background">
<shape android:shape="rectangle">
<gradient
android:angle="90"
android:endColor="@color/colorPrimaryDark"
android:startColor="@color/colorPrimaryDark"
android:type="linear" />
<corners android:radius="0dp" />
</shape>
</item>
</ripple>
Now your design look like this
Step 3: Coding the Functionality
In your Java file, which is almost always MainActivity.java by default, head on over to the MainActivity extends AppCompatActivity class. Copy bellow code and paste into your MainActivity.kt file. But without changing your project package name [ package com.andrious.simplecalculator; ]
import android.content.res.Configuration
import android.graphics.Color
import android.os.Bundle
import android.util.TypedValue
import android.view.View
import android.widget.Button
import android.widget.ImageButton
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
var result_value: Double = 0.0
var checker:Boolean = true
var orientation = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var button_0 = findViewById(R.id.button_0) as Button
var button_1 = findViewById(R.id.button_1) as Button
var button_2 = findViewById(R.id.button_2) as Button
var button_3 = findViewById(R.id.button_3) as Button
var button_4 = findViewById(R.id.button_4) as Button
var button_5 = findViewById(R.id.button_5) as Button
var button_6 = findViewById(R.id.button_6) as Button
var button_7 = findViewById(R.id.button_7) as Button
var button_8 = findViewById(R.id.button_8) as Button
var button_9 = findViewById(R.id.button_9) as Button
var button_add = findViewById(R.id.button_add) as Button
var button_sub = findViewById(R.id.button_sub) as Button
var button_multi = findViewById(R.id.button_multi) as Button
var button_div = findViewById(R.id.button_div) as Button
var button_modulas = findViewById(R.id.button_modulas) as Button
var button_dot = findViewById(R.id.button_dot) as Button
var button_equal = findViewById(R.id.button_equal) as Button
var button_clear = findViewById(R.id.button_clear) as Button
var button_back = findViewById(R.id.button_back) as ImageButton
var result = findViewById(R.id.result) as TextView
var display = findViewById(R.id.display) as TextView
orientation = resources.configuration.orientation
button_modulas.isEnabled = false
entry_controller(checker)
button_0.setOnClickListener(View.OnClickListener {
display.text = display.text.toString() + "0"
text_size_color_controller();
checker = false
entry_controller(checker)
})
button_1.setOnClickListener(View.OnClickListener {
display.text = display.text.toString() + "1"
text_size_color_controller();
checker = false
entry_controller(checker)
})
button_2.setOnClickListener(View.OnClickListener {
display.text = display.text.toString() + "2"
text_size_color_controller();
checker = false
entry_controller(checker)
})
button_3.setOnClickListener(View.OnClickListener {
display.text = display.text.toString() + "3"
text_size_color_controller();
checker = false
entry_controller(checker)
})
button_4.setOnClickListener(View.OnClickListener {
display.text = display.text.toString() + "4"
text_size_color_controller();
checker = false
entry_controller(checker)
})
button_5.setOnClickListener(View.OnClickListener {
display.text = display.text.toString() + "5"
text_size_color_controller()
checker = false
entry_controller(checker)
})
button_6.setOnClickListener(View.OnClickListener {
display.text = display.text.toString() + "6"
text_size_color_controller()
checker = false
entry_controller(checker)
})
button_7.setOnClickListener(View.OnClickListener {
display.text = display.text.toString() + "7"
text_size_color_controller()
checker = false
entry_controller(checker)
})
button_8.setOnClickListener(View.OnClickListener {
display.text = display.text.toString() + "8"
text_size_color_controller()
checker = false
entry_controller(checker)
})
button_9.setOnClickListener(View.OnClickListener {
display.text = display.text.toString() + "9"
text_size_color_controller()
checker = false
entry_controller(checker)
})
button_dot.setOnClickListener(View.OnClickListener {
display.text = display.text.toString() + "."
text_size_color_controller()
checker = false
entry_controller(checker)
})
button_add.setOnClickListener(View.OnClickListener {
display.text = display.text.toString() + "+"
text_size_color_controller()
checker = true
entry_controller(checker)
})
button_sub.setOnClickListener(View.OnClickListener {
display.text = display.text.toString() + "-"
text_size_color_controller()
checker = true
entry_controller(checker)
})
button_multi.setOnClickListener(View.OnClickListener {
display.text = display.text.toString() + "*"
text_size_color_controller()
checker = true
entry_controller(checker)
})
button_div.setOnClickListener(View.OnClickListener {
display.text = display.text.toString() + "/"
text_size_color_controller()
checker = true
entry_controller(checker)
})
button_modulas.setOnClickListener(View.OnClickListener {
result.text = "=" + (result_value/100.0).toString()
})
button_clear.setOnClickListener(View.OnClickListener {
display.text = ""
result.text = ""
result.visibility = View.GONE
display.setTextSize(TypedValue.COMPLEX_UNIT_DIP,36F)
})
button_back.setOnClickListener(View.OnClickListener {
var data = display.text.toString()
if(data.length > 0){
display.text = data.substring(0, data.length - 1)
text_size_color_controller();
}
})
button_equal.setOnClickListener(View.OnClickListener {
var data = display.text.toString()
if(!data.endsWith("+") || !data.endsWith("-") || !data.endsWith("*") || !data.endsWith("/")){
result_value = calculation(data)
result.visibility = View.VISIBLE
result.text = "= " + String.format("%.5f", result_value).toDouble().toString()
display.setTextColor(Color.parseColor("#bdbdbd"))
result.setTextColor(Color.parseColor("#000000"))
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
// In landscape
display.setTextSize(TypedValue.COMPLEX_UNIT_DIP,26F)
result.setTextSize(TypedValue.COMPLEX_UNIT_DIP,20F)
} else {
// In portrait
display.setTextSize(TypedValue.COMPLEX_UNIT_DIP,26F)
result.setTextSize(TypedValue.COMPLEX_UNIT_DIP,36F)
}
button_modulas.isEnabled = true
}
})
}
fun text_size_color_controller(): Void? {
display.setTextColor(Color.parseColor("#000000"))
result.setTextColor(Color.parseColor("#bdbdbd"))
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
// In landscape
display.setTextSize(TypedValue.COMPLEX_UNIT_DIP,30F)
result.setTextSize(TypedValue.COMPLEX_UNIT_DIP,20F)
} else {
// In portrait
display.setTextSize(TypedValue.COMPLEX_UNIT_DIP,36F)
result.setTextSize(TypedValue.COMPLEX_UNIT_DIP,26F)
}
button_modulas.isEnabled = false
return null
}
fun entry_controller(b:Boolean): Void? {
if(b){
button_add.isEnabled = false
button_sub.isEnabled = false
button_multi.isEnabled = false
button_div.isEnabled = false
button_equal.isEnabled = false
}else{
button_add.isEnabled = true
button_sub.isEnabled = true
button_multi.isEnabled = true
button_div.isEnabled = true
button_equal.isEnabled = true
}
return null
}
fun calculation(str: String): Double {
return object : Any() {
var pos = -1
var ch = 0
fun nextChar() {
if(++pos < str.length){
ch = str[pos].toInt()
}else{
ch = -1
}
}
fun eat(charToEat: Int): Boolean {
while (ch == ' '.toInt()) nextChar()
if (ch == charToEat) {
nextChar()
return true
}
return false
}
fun parse(): Double {
nextChar()
val x = parseExpression()
if (pos < str.length) throw RuntimeException("Unexpected: " + ch.toChar())
return x
}
// Grammar:
// expression = term | expression `+` term | expression `-` term
// term = factor | term `*` factor | term `/` factor
// factor = `+` factor | `-` factor | `(` expression `)`
// | number | functionName factor | factor `^` factor
fun parseExpression(): Double {
var x = parseTerm()
while (true) {
if (eat('+'.toInt())) x += parseTerm() // addition
else if (eat('-'.toInt())) x -= parseTerm() // subtraction
else return x
}
}
fun parseTerm(): Double {
var x = parseFactor()
while (true) {
if (eat('*'.toInt())) x *= parseFactor() // multiplication
else if (eat('/'.toInt())) x /= parseFactor() // division
else return x
}
}
fun parseFactor(): Double {
if (eat('+'.toInt())) return parseFactor() // unary plus
if (eat('-'.toInt())) return -parseFactor() // unary minus
var x: Double
val startPos = pos
if (eat('('.toInt())) { // parentheses
x = parseExpression()
eat(')'.toInt())
} else if (ch >= '0'.toInt() && ch <= '9'.toInt() || ch == '.'.toInt()) { // numbers
while (ch >= '0'.toInt() && ch <= '9'.toInt() || ch == '.'.toInt()) nextChar()
x = str.substring(startPos, pos).toDouble()
} else if (ch >= 'a'.toInt() && ch <= 'z'.toInt()) { // functions
while (ch >= 'a'.toInt() && ch <= 'z'.toInt()) nextChar()
val func = str.substring(startPos, pos)
x = parseFactor()
x =
if (func == "sqrt") Math.sqrt(x) else if (func == "sin") Math.sin(
Math.toRadians(
x
)
) else if (func == "cos") Math.cos(Math.toRadians(x)) else if (func == "tan") Math.tan(
Math.toRadians(x)
) else throw RuntimeException(
"Unknown function: $func"
)
} else {
throw RuntimeException("Unexpected: " + ch.toChar())
}
if (eat('^'.toInt())) x = Math.pow(x, parseFactor()) // exponentiation
return x
}
}.parse()
}
}
Now every thing is done. Run and enjoy the calculator app.
Step 4: Function description
Fetching values from the elements into the working of our app
Inside the onCreate function, we will fetch all values and assign them to our objects. We do this by the following code
var button_0 = findViewById(R.id.button_0) as Button
Here, we are fetching the value of ‘button_0’, which is the ID of our button zero, and storing it in the object ‘button_0’ that we created earlier. Though they are named the same, Android Studio can identify the correct one. But if it gets confusing for you, feel free to give either one of them any other names.
We do the same with our TextView.
var display = findViewById(R.id.display) as TextView
Changing the TextView value by pressing the buttons.
button_0.setOnClickListener(View.OnClickListener {
display.text = display.text.toString() + "0"
text_size_color_controller();
checker = false
entry_controller(checker)
})
We use OnClickListener for this part of the program. This is what happens when you push zero. The TextView, first already fetches the value that it is already displaying, null in this case, and then adds 0 to it.
Text Font size control when change the phone orientation.
First declare a global variable
var orientation = 0
In onCreate method we initialize it and get the device current orientation.
orientation = resources.configuration.orientation
Finally use conditional statement in button_equal onClick function based on device orientation.
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
// In landscape
display.setTextSize(TypedValue.COMPLEX_UNIT_DIP,26F)
result.setTextSize(TypedValue.COMPLEX_UNIT_DIP,20F)
} else {
// In portrait
display.setTextSize(TypedValue.COMPLEX_UNIT_DIP,26F)
result.setTextSize(TypedValue.COMPLEX_UNIT_DIP,36F)
}
Text size and color control function
fun text_size_color_controller(): Void? {
display.setTextColor(Color.parseColor("#000000"))
result.setTextColor(Color.parseColor("#bdbdbd"))
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
// In landscape
display.setTextSize(TypedValue.COMPLEX_UNIT_DIP,30F)
result.setTextSize(TypedValue.COMPLEX_UNIT_DIP,20F)
} else {
// In portrait
display.setTextSize(TypedValue.COMPLEX_UNIT_DIP,36F)
result.setTextSize(TypedValue.COMPLEX_UNIT_DIP,26F)
}
button_modulas.isEnabled = false
return null
}
This function control text size and color when equal button click. This function also check the device orientation for controlling the text size.
User Entry Control Function
fun entry_controller(b:Boolean): Void? {
if(b){
button_add.isEnabled = false
button_sub.isEnabled = false
button_multi.isEnabled = false
button_div.isEnabled = false
button_equal.isEnabled = false
}else{
button_add.isEnabled = true
button_sub.isEnabled = true
button_multi.isEnabled = true
button_div.isEnabled = true
button_equal.isEnabled = true
}
return null
}
This function work like this if user don’t write any number but click addition or subtraction button, this function handle this type of error. If user don’t type any number then all the operation button are disabled. Other exception is if user write like this 2+2+ and press enter then app will be crashed. This function also handle this. If user input last value is any operator then equal button automatically disabled. It also handle if user click any operator button then all the operator buttons are automatically disabled. If user need to change the operator click the back button then automatically enable all the operator buttons.
Calculation Function
fun calculation(str: String): Double {
return object : Any() {
var pos = -1
var ch = 0
fun nextChar() {
if(++pos < str.length){
ch = str[pos].toInt()
}else{
ch = -1
}
}
fun eat(charToEat: Int): Boolean {
while (ch == ' '.toInt()) nextChar()
if (ch == charToEat) {
nextChar()
return true
}
return false
}
fun parse(): Double {
nextChar()
val x = parseExpression()
if (pos < str.length) throw RuntimeException("Unexpected: " + ch.toChar())
return x
}
// Grammar:
// expression = term | expression `+` term | expression `-` term
// term = factor | term `*` factor | term `/` factor
// factor = `+` factor | `-` factor | `(` expression `)`
// | number | functionName factor | factor `^` factor
fun parseExpression(): Double {
var x = parseTerm()
while (true) {
if (eat('+'.toInt())) x += parseTerm() // addition
else if (eat('-'.toInt())) x -= parseTerm() // subtraction
else return x
}
}
fun parseTerm(): Double {
var x = parseFactor()
while (true) {
if (eat('*'.toInt())) x *= parseFactor() // multiplication
else if (eat('/'.toInt())) x /= parseFactor() // division
else return x
}
}
fun parseFactor(): Double {
if (eat('+'.toInt())) return parseFactor() // unary plus
if (eat('-'.toInt())) return -parseFactor() // unary minus
var x: Double
val startPos = pos
if (eat('('.toInt())) { // parentheses
x = parseExpression()
eat(')'.toInt())
} else if (ch >= '0'.toInt() && ch <= '9'.toInt() || ch == '.'.toInt()) { // numbers
while (ch >= '0'.toInt() && ch <= '9'.toInt() || ch == '.'.toInt()) nextChar()
x = str.substring(startPos, pos).toDouble()
} else if (ch >= 'a'.toInt() && ch <= 'z'.toInt()) { // functions
while (ch >= 'a'.toInt() && ch <= 'z'.toInt()) nextChar()
val func = str.substring(startPos, pos)
x = parseFactor()
x =
if (func == "sqrt") Math.sqrt(x) else if (func == "sin") Math.sin(
Math.toRadians(
x
)
) else if (func == "cos") Math.cos(Math.toRadians(x)) else if (func == "tan") Math.tan(
Math.toRadians(x)
) else throw RuntimeException(
"Unknown function: $func"
)
} else {
throw RuntimeException("Unexpected: " + ch.toChar())
}
if (eat('^'.toInt())) x = Math.pow(x, parseFactor()) // exponentiation
return x
}
}.parse()
}
When user click equal button then equal button onClickListener function get the all user input as string then pass it int this calculation function. This function phrase the string and calculate the value and return result as decimal data type.
Leave a Comment
(0 Comments)