From 4614299dac98605e9d8cfafb5a2d395011cbbfdf Mon Sep 17 00:00:00 2001 From: Bryan Garland Date: Wed, 22 Jan 2025 20:49:36 -0500 Subject: [PATCH 01/13] Add fraction results and precision. Needs tests and tweaking --- .../opencalculator/MyPreferences.kt | 7 +++- .../opencalculator/activities/MainActivity.kt | 26 +++++++++++-- .../opencalculator/calculator/Fraction.kt | 39 +++++++++++++++++++ app/src/main/res/values/arrays.xml | 24 ++++++++++++ app/src/main/res/values/strings.xml | 6 +++ app/src/main/res/xml/root_preferences.xml | 18 +++++++++ 6 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt diff --git a/app/src/main/java/com/darkempire78/opencalculator/MyPreferences.kt b/app/src/main/java/com/darkempire78/opencalculator/MyPreferences.kt index 8211e410..0add7c52 100644 --- a/app/src/main/java/com/darkempire78/opencalculator/MyPreferences.kt +++ b/app/src/main/java/com/darkempire78/opencalculator/MyPreferences.kt @@ -28,6 +28,8 @@ class MyPreferences(context: Context) { private const val KEY_SPLIT_PARENTHESIS_BUTTON = "darkempire78.opencalculator.SPLIT_PARENTHESIS_BUTTON" private const val KEY_DELETE_HISTORY_ON_SWIPE = "darkempire78.opencalculator.DELETE_HISTORY_ELEMENT_ON_SWIPE" private const val KEY_AUTO_SAVE_CALCULATION_WITHOUT_EQUAL_BUTTON = "darkempire78.opencalculator.AUTO_SAVE_CALCULATION_WITHOUT_EQUAL_BUTTON" + private const val KEY_SHOW_FRACTION = "darkempire78.opencalculator.SHOW_FRACTION" + private const val KEY_FRACTION_PRECISION = "darkempire78.opencalculator.FRACTION_PRECISION" } private val preferences = PreferenceManager.getDefaultSharedPreferences(context) @@ -65,7 +67,10 @@ class MyPreferences(context: Context) { var autoSaveCalculationWithoutEqualButton = preferences.getBoolean(KEY_AUTO_SAVE_CALCULATION_WITHOUT_EQUAL_BUTTON, true) set(value) = preferences.edit().putBoolean(KEY_AUTO_SAVE_CALCULATION_WITHOUT_EQUAL_BUTTON, value).apply() - + var showResultFraction = preferences.getBoolean(KEY_SHOW_FRACTION, false) + set(value) = preferences.edit().putBoolean(KEY_SHOW_FRACTION, value).apply() + var fractionPrecision = preferences.getString(KEY_FRACTION_PRECISION, "4") + set(value) = preferences.edit().putString(KEY_FRACTION_PRECISION, value).apply() fun getHistory(): MutableList { diff --git a/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt b/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt index 85717553..fb20bf6c 100644 --- a/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt +++ b/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt @@ -34,6 +34,7 @@ import com.darkempire78.opencalculator.calculator.parser.NumberFormatter import com.darkempire78.opencalculator.R import com.darkempire78.opencalculator.TextSizeAdjuster import com.darkempire78.opencalculator.Themes +import com.darkempire78.opencalculator.calculator.decimalToFraction import com.darkempire78.opencalculator.databinding.ActivityMainBinding import com.darkempire78.opencalculator.calculator.division_by_0 import com.darkempire78.opencalculator.calculator.domain_error @@ -68,6 +69,7 @@ class MainActivity : AppCompatActivity() { private var isEqualLastAction = false private var isDegreeModeActivated = true // Set degree by default private var errorStatusOld = false + private var showFraction = false // default private var isStillTheSameCalculation_autoSaveCalculationWithoutEqualOption = false private var lastHistoryElementId = "" @@ -209,6 +211,11 @@ class MainActivity : AppCompatActivity() { toggleDegreeMode() } + // Show result fractions if enabled + if (MyPreferences(this).showResultFraction) { + showFraction = !showFraction + } + // Focus by default binding.input.requestFocus() @@ -392,6 +399,11 @@ class MainActivity : AppCompatActivity() { } } + private fun getFractionPrecision(): String { + val fractionPrecision = MyPreferences(this).fractionPrecision + return fractionPrecision.toString() + } + private fun setErrorColor(errorStatus: Boolean) { // Only run if the color needs to be updated runOnUiThread { @@ -641,10 +653,18 @@ class MainActivity : AppCompatActivity() { } withContext(Dispatchers.Main) { - if (formattedResult != calculation) { - binding.resultDisplay.text = formattedResult + if (showFraction) { + val precision = getFractionPrecision().toDouble() + if (formattedResult != calculation || '.' !in formattedResult) { + binding.resultDisplay.text = formattedResult + } else { + binding.resultDisplay.text = + decimalToFraction(calculationResult.toDouble(), precision) + } } else { - binding.resultDisplay.text = "" + if (formattedResult != calculation) { + binding.resultDisplay.text = formattedResult + } } } diff --git a/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt b/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt new file mode 100644 index 00000000..bb29e6f3 --- /dev/null +++ b/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt @@ -0,0 +1,39 @@ +package com.darkempire78.opencalculator.calculator + +import com.darkempire78.opencalculator.MyPreferences +import kotlin.math.abs +import kotlin.math.floor + +fun decimalToFraction(decimal: Double, precision: Double): String { + // val precision = 1.0E-4 + var n1 = 1 + var n2 = 0 + var d1 = 0 + var d2 = 1 + var b = decimal + val base = floor(b).toInt() + var dec = decimal - base.toDouble() + val dec2 = dec + do { + val a = floor(dec).toInt() + val numer = n1 + val denom = d1 + n1 = a * n1 + n2 + n2 = numer + d1 = a * d1 + d2 + d2 = denom + dec = 1 / (dec - a) + } while (abs(dec2 - n1.toDouble() / d1) > dec2 * precision) + if (base != 0) { + return "$base $n1/$d1" + } + if (n1 > d1) { + val whole = n1 / d1 + n1 -= whole * d1 + if (n1 == 0) { + return "$whole" + } + return "$whole $n1/$d1" + } + return "$n1/$d1" +} \ No newline at end of file diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index e8c2b47b..dcced70e 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -86,4 +86,28 @@ 1000 + + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + + + + 1.0E-2 + 1.0E-3 + 1.0E-4 + 1.0E-5 + 1.0E-6 + 1.0E-7 + 1.0E-8 + 1.0E-9 + 1.0E-10 + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cbd9561e..bee5a779 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -84,6 +84,7 @@ FORMATTING HISTORY ADVANCED + FRACTIONS Language @@ -120,6 +121,11 @@ Keep device awake Prevent device from sleeping while the app is in the foreground + Show Fractions + Display results as fractions as well as decimals + Fraction precision + How many decimal places before rounding occurs. Anything over will result in fraction rounding + HELP US SOCIAL diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml index 4aaf942f..c5f58ec8 100644 --- a/app/src/main/res/xml/root_preferences.xml +++ b/app/src/main/res/xml/root_preferences.xml @@ -88,6 +88,24 @@ + + + + + From c72dc6614150c5c67c05ec0ec5166139391abbf1 Mon Sep 17 00:00:00 2001 From: Bryan Garland Date: Wed, 29 Jan 2025 11:29:36 -0500 Subject: [PATCH 02/13] Moved setting check to onResume() --- .../opencalculator/activities/MainActivity.kt | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt b/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt index ceb34fe4..a9dd5de1 100644 --- a/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt +++ b/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt @@ -215,11 +215,6 @@ class MainActivity : AppCompatActivity() { toggleDegreeMode() } - // Show result fractions if enabled - if (MyPreferences(this).showResultFraction) { - showFraction = !showFraction - } - // Focus by default binding.input.requestFocus() @@ -1263,6 +1258,14 @@ class MainActivity : AppCompatActivity() { binding.resultDisplay.text = "" } + // Show result fractions if enabled + if (MyPreferences(this).showResultFraction) { + showFraction = true + } else { + showFraction = false + } + + // Split the parentheses button (if option is enabled) if (MyPreferences(this).splitParenthesisButton) { // Hide the AC button From 8d8c202c58648919de06e8b628ea49fd2b5317be Mon Sep 17 00:00:00 2001 From: Bryan Garland Date: Wed, 29 Jan 2025 11:43:01 -0500 Subject: [PATCH 03/13] Remove unnecessary check --- .../com/darkempire78/opencalculator/activities/MainActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt b/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt index a9dd5de1..26012c70 100644 --- a/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt +++ b/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt @@ -658,7 +658,7 @@ class MainActivity : AppCompatActivity() { withContext(Dispatchers.Main) { if (showFraction) { val precision = getFractionPrecision().toDouble() - if (formattedResult != calculation || '.' !in formattedResult) { + if (formattedResult != calculation) { binding.resultDisplay.text = formattedResult } else { binding.resultDisplay.text = From ff81790f773244fea740eab1748d484c19eb5e32 Mon Sep 17 00:00:00 2001 From: Bryan Garland Date: Sun, 27 Apr 2025 16:37:14 -0400 Subject: [PATCH 04/13] Change string output to use spannable --- .../opencalculator/activities/MainActivity.kt | 20 +++++---- .../opencalculator/calculator/Fraction.kt | 42 +++++++++++-------- 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt b/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt index 9be62921..bdae4b42 100644 --- a/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt +++ b/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt @@ -18,6 +18,7 @@ import android.view.WindowManager import android.view.accessibility.AccessibilityEvent import android.widget.Button import android.widget.HorizontalScrollView +import android.widget.TextView import android.widget.Toast import androidx.activity.addCallback import androidx.appcompat.app.AppCompatActivity @@ -31,9 +32,8 @@ import com.darkempire78.opencalculator.MyPreferences import com.darkempire78.opencalculator.R import com.darkempire78.opencalculator.TextSizeAdjuster import com.darkempire78.opencalculator.Themes -import com.darkempire78.opencalculator.calculator.decimalToFraction -import com.darkempire78.opencalculator.databinding.ActivityMainBinding import com.darkempire78.opencalculator.calculator.Calculator +import com.darkempire78.opencalculator.calculator.decimalToFraction import com.darkempire78.opencalculator.calculator.division_by_0 import com.darkempire78.opencalculator.calculator.domain_error import com.darkempire78.opencalculator.calculator.is_infinity @@ -630,18 +630,18 @@ class MainActivity : AppCompatActivity() { } withContext(Dispatchers.Main) { - if (showFraction) { + if (showFraction && '.' in calculation) { + val tView = findViewById(R.id.resultDisplay) val precision = getFractionPrecision().toDouble() if (formattedResult != calculation) { binding.resultDisplay.text = formattedResult } else { - binding.resultDisplay.text = - decimalToFraction(calculationResult.toDouble(), precision) + decimalToFraction(calculation, precision, tView) } + } else if (formattedResult != calculation){ + binding.resultDisplay.text = formattedResult } else { - if (formattedResult != calculation) { - binding.resultDisplay.text = formattedResult - } + binding.resultDisplay.text = "" } } @@ -1033,7 +1033,9 @@ class MainActivity : AppCompatActivity() { } // Display result - withContext(Dispatchers.Main) { binding.input.setText(formattedResult) } + withContext(Dispatchers.Main) { + binding.input.setText(formattedResult) + } // Set cursor withContext(Dispatchers.Main) { diff --git a/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt b/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt index bb29e6f3..eabb267a 100644 --- a/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt +++ b/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt @@ -1,19 +1,25 @@ package com.darkempire78.opencalculator.calculator -import com.darkempire78.opencalculator.MyPreferences +import android.text.Spannable +import android.text.SpannableStringBuilder +import android.text.style.RelativeSizeSpan +import android.text.style.SuperscriptSpan +import android.widget.TextView import kotlin.math.abs import kotlin.math.floor -fun decimalToFraction(decimal: Double, precision: Double): String { - // val precision = 1.0E-4 +fun decimalToFraction(calculation: String, precision: Double, textView: TextView) { + + val decimalPosition = calculation.indexOf('.') + val base = calculation.substring(0, decimalPosition) + var dec = calculation.substring(decimalPosition).toDouble() + var n1 = 1 var n2 = 0 var d1 = 0 var d2 = 1 - var b = decimal - val base = floor(b).toInt() - var dec = decimal - base.toDouble() val dec2 = dec + do { val a = floor(dec).toInt() val numer = n1 @@ -24,16 +30,18 @@ fun decimalToFraction(decimal: Double, precision: Double): String { d2 = denom dec = 1 / (dec - a) } while (abs(dec2 - n1.toDouble() / d1) > dec2 * precision) - if (base != 0) { - return "$base $n1/$d1" - } - if (n1 > d1) { - val whole = n1 / d1 - n1 -= whole * d1 - if (n1 == 0) { - return "$whole" - } - return "$whole $n1/$d1" + + if (base != "0") { + val tempString = "$base $n1/$d1" + val stringSpan = SpannableStringBuilder(tempString) + val spaceLoc = stringSpan.indexOf(' ') + val stringLen = stringSpan.length + stringSpan.setSpan(SuperscriptSpan(),spaceLoc, stringLen, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) + stringSpan.setSpan(RelativeSizeSpan(0.6f),spaceLoc, stringLen, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) + textView.setText(stringSpan) + } else { + val tempString = "$n1/$d1" + val stringSpan = SpannableStringBuilder(tempString) + textView.setText(stringSpan) } - return "$n1/$d1" } \ No newline at end of file From 3969f7442ac00fba8d6e85c35ceb61075c2677a3 Mon Sep 17 00:00:00 2001 From: Bryan Garland Date: Sun, 11 May 2025 12:57:24 -0400 Subject: [PATCH 05/13] Moved function to only run when '=' pressed --- .../opencalculator/activities/MainActivity.kt | 26 ++++++------------- app/src/main/res/xml/root_preferences.xml | 12 ++++----- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt b/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt index dd027a3e..df9851c3 100644 --- a/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt +++ b/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt @@ -11,7 +11,6 @@ import android.os.Build import android.os.Bundle import android.text.Editable import android.text.TextWatcher -import android.util.Log import android.view.HapticFeedbackConstants import android.view.MenuItem import android.view.View @@ -633,22 +632,6 @@ class MainActivity : AppCompatActivity() { } } - withContext(Dispatchers.Main) { - if (showFraction && '.' in calculation) { - val tView = findViewById(R.id.resultDisplay) - val precision = getFractionPrecision().toDouble() - if (formattedResult != calculation) { - binding.resultDisplay.text = formattedResult - } else { - decimalToFraction(calculation, precision, tView) - } - } else if (formattedResult != calculation){ - binding.resultDisplay.text = formattedResult - } else { - binding.resultDisplay.text = "" - } - } - // Save to history if the option autoSaveCalculationWithoutEqualButton is enabled if (MyPreferences(this@MainActivity).autoSaveCalculationWithoutEqualButton) { if (calculation != formattedResult) { @@ -1040,6 +1023,11 @@ class MainActivity : AppCompatActivity() { // Display result withContext(Dispatchers.Main) { binding.input.setText(formattedResult) + if (showFraction && '.' in formattedResult) { + val tView = findViewById(R.id.resultDisplay) + val precision = getFractionPrecision().toDouble() + decimalToFraction(formattedResult, precision, tView) + } } // Set cursor @@ -1051,7 +1039,9 @@ class MainActivity : AppCompatActivity() { binding.input.isCursorVisible = false // Clear resultDisplay - binding.resultDisplay.text = "" + if (!showFraction) { + binding.resultDisplay.text = "" + } } if (calculation != formattedResult) { diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml index d79d6b4d..031cecc2 100644 --- a/app/src/main/res/xml/root_preferences.xml +++ b/app/src/main/res/xml/root_preferences.xml @@ -101,19 +101,19 @@ app:title="@string/settings_category_fractions"> + app:icon="@drawable/precision" + app:key="darkempire78.opencalculator.FRACTION_PRECISION" + app:summary="@string/settings_fractions_precision_desc" + app:title="@string/settings_fractions_precision" /> Date: Sun, 11 May 2025 22:18:25 -0400 Subject: [PATCH 06/13] Added icons for fractions and fraction precision --- .../darkempire78/opencalculator/calculator/Fraction.kt | 4 ++-- app/src/main/res/drawable/fracprec.xml | 9 +++++++++ app/src/main/res/drawable/ftfrac.xml | 8 ++++++++ app/src/main/res/xml/root_preferences.xml | 3 ++- 4 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 app/src/main/res/drawable/fracprec.xml create mode 100644 app/src/main/res/drawable/ftfrac.xml diff --git a/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt b/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt index eabb267a..9f1ad016 100644 --- a/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt +++ b/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt @@ -38,10 +38,10 @@ fun decimalToFraction(calculation: String, precision: Double, textView: TextView val stringLen = stringSpan.length stringSpan.setSpan(SuperscriptSpan(),spaceLoc, stringLen, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) stringSpan.setSpan(RelativeSizeSpan(0.6f),spaceLoc, stringLen, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) - textView.setText(stringSpan) + textView.text = stringSpan } else { val tempString = "$n1/$d1" val stringSpan = SpannableStringBuilder(tempString) - textView.setText(stringSpan) + textView.text = stringSpan } } \ No newline at end of file diff --git a/app/src/main/res/drawable/fracprec.xml b/app/src/main/res/drawable/fracprec.xml new file mode 100644 index 00000000..d0f59a38 --- /dev/null +++ b/app/src/main/res/drawable/fracprec.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ftfrac.xml b/app/src/main/res/drawable/ftfrac.xml new file mode 100644 index 00000000..0f46fe6d --- /dev/null +++ b/app/src/main/res/drawable/ftfrac.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml index 031cecc2..c9bcd336 100644 --- a/app/src/main/res/xml/root_preferences.xml +++ b/app/src/main/res/xml/root_preferences.xml @@ -102,6 +102,7 @@ From eff0759d1c5686f704b0fedef6f808c648b5db57 Mon Sep 17 00:00:00 2001 From: Bryan Garland Date: Fri, 18 Jul 2025 15:19:43 -0400 Subject: [PATCH 07/13] Added fraction tests --- .../opencalculator/FractionTests.kt | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 app/src/androidTest/java/com/darkempire78/opencalculator/FractionTests.kt diff --git a/app/src/androidTest/java/com/darkempire78/opencalculator/FractionTests.kt b/app/src/androidTest/java/com/darkempire78/opencalculator/FractionTests.kt new file mode 100644 index 00000000..c5e86b55 --- /dev/null +++ b/app/src/androidTest/java/com/darkempire78/opencalculator/FractionTests.kt @@ -0,0 +1,48 @@ +package com.darkempire78.opencalculator + +import android.content.Context +import android.widget.TextView +import androidx.test.core.app.ApplicationProvider +import com.darkempire78.opencalculator.calculator.decimalToFraction +import org.junit.Assert.assertEquals +import org.junit.Test + +class FractionTests { + val context: Context = ApplicationProvider.getApplicationContext() + val view = TextView(context) + + @Test + fun testFraction(){ + val dec = "4.563" + decimalToFraction(dec, 1.0E-4, view) + assertEquals("4 67/119", view.text.toString()) + } + + @Test + fun testLessThanOneWithZero(){ + val dec = "0.345" + decimalToFraction(dec, 1.0E-4, view) + assertEquals("69/200", view.text.toString()) + } + + @Test + fun testLessThanOneWithoutZero(){ + val dec = ".345" + decimalToFraction(dec, 1.0E-4, view) + assertEquals("69/200", view.text.toString()) + } + + @Test + fun testRepeatDecimalRounding(){ + val dec = "3.33333" + decimalToFraction(dec, 1.0E-4, view) + assertEquals("3 1/3", view.text.toString()) + } + + @Test + fun testRepeatDecimalNoRounding(){ + val dec = "3.33333" + decimalToFraction(dec, 1.0E-5, view) + assertEquals("3 33333/100000", view.text.toString()) + } +} \ No newline at end of file From c568e61761db0b76e7c65ac3510c60b0f50c78b3 Mon Sep 17 00:00:00 2001 From: Bryan Garland Date: Fri, 18 Jul 2025 15:20:28 -0400 Subject: [PATCH 08/13] Added fraction tests --- .../opencalculator/calculator/Fraction.kt | 40 ++++++++++++++----- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt b/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt index 9f1ad016..885743a2 100644 --- a/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt +++ b/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt @@ -11,14 +11,18 @@ import kotlin.math.floor fun decimalToFraction(calculation: String, precision: Double, textView: TextView) { val decimalPosition = calculation.indexOf('.') - val base = calculation.substring(0, decimalPosition) - var dec = calculation.substring(decimalPosition).toDouble() + var decimal = calculation.substring(decimalPosition).toDouble() + val whole = if (decimalPosition > 0) calculation.substring(0, decimalPosition).toInt() else 0 var n1 = 1 var n2 = 0 var d1 = 0 var d2 = 1 - val dec2 = dec + + var b = decimal + val base = floor(b).toInt() + var dec = decimal // - base.toDouble() + val dec2 = decimal do { val a = floor(dec).toInt() @@ -31,14 +35,28 @@ fun decimalToFraction(calculation: String, precision: Double, textView: TextView dec = 1 / (dec - a) } while (abs(dec2 - n1.toDouble() / d1) > dec2 * precision) - if (base != "0") { - val tempString = "$base $n1/$d1" - val stringSpan = SpannableStringBuilder(tempString) - val spaceLoc = stringSpan.indexOf(' ') - val stringLen = stringSpan.length - stringSpan.setSpan(SuperscriptSpan(),spaceLoc, stringLen, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) - stringSpan.setSpan(RelativeSizeSpan(0.6f),spaceLoc, stringLen, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) - textView.text = stringSpan + if (whole != 0) { + if (n1 == 0) { + textView.text = whole.toString() + } else { + val tempString = "$whole $n1/$d1" + val stringSpan = SpannableStringBuilder(tempString) + val spaceLoc = stringSpan.indexOf(' ') + val stringLen = stringSpan.length + stringSpan.setSpan( + SuperscriptSpan(), + spaceLoc, + stringLen, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE + ) + stringSpan.setSpan( + RelativeSizeSpan(0.6f), + spaceLoc, + stringLen, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE + ) + textView.text = stringSpan + } } else { val tempString = "$n1/$d1" val stringSpan = SpannableStringBuilder(tempString) From 84e9170c46de92dffb7d9480582c554ebe2857c7 Mon Sep 17 00:00:00 2001 From: Bryan Garland Date: Fri, 18 Jul 2025 15:22:39 -0400 Subject: [PATCH 09/13] Garbage cleanup --- .../java/com/darkempire78/opencalculator/calculator/Fraction.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt b/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt index 885743a2..f69aee84 100644 --- a/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt +++ b/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt @@ -19,8 +19,6 @@ fun decimalToFraction(calculation: String, precision: Double, textView: TextView var d1 = 0 var d2 = 1 - var b = decimal - val base = floor(b).toInt() var dec = decimal // - base.toDouble() val dec2 = decimal From 1283b432d0f355f33e2a1e52fe26a949f7124608 Mon Sep 17 00:00:00 2001 From: Bryan Garland Date: Mon, 15 Sep 2025 18:02:43 -0400 Subject: [PATCH 10/13] Fixed default fraction precision and output --- .../darkempire78/opencalculator/MyPreferences.kt | 2 +- .../opencalculator/activities/MainActivity.kt | 8 ++------ .../opencalculator/calculator/Fraction.kt | 14 +++++++++++--- app/src/main/res/values/arrays.xml | 2 +- app/src/main/res/xml/root_preferences.xml | 2 +- 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/darkempire78/opencalculator/MyPreferences.kt b/app/src/main/java/com/darkempire78/opencalculator/MyPreferences.kt index b277ad5e..086d2bbe 100644 --- a/app/src/main/java/com/darkempire78/opencalculator/MyPreferences.kt +++ b/app/src/main/java/com/darkempire78/opencalculator/MyPreferences.kt @@ -72,7 +72,7 @@ class MyPreferences(context: Context) { var showResultFraction = preferences.getBoolean(KEY_SHOW_FRACTION, false) set(value) = preferences.edit().putBoolean(KEY_SHOW_FRACTION, value).apply() - var fractionPrecision = preferences.getString(KEY_FRACTION_PRECISION, "4") + var fractionPrecision = preferences.getString(KEY_FRACTION_PRECISION, "1.0E-4") set(value) = preferences.edit().putString(KEY_FRACTION_PRECISION, value).apply() var numberingSystem = preferences.getInt(KEY_NUMBERING_SYSTEM, 0) set(value) = preferences.edit().putInt(KEY_NUMBERING_SYSTEM, value).apply() diff --git a/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt b/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt index 36ecbff6..ae740f35 100644 --- a/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt +++ b/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt @@ -1045,7 +1045,7 @@ class MainActivity : AppCompatActivity() { if (showFraction && '.' in formattedResult) { val tView = findViewById(R.id.resultDisplay) val precision = getFractionPrecision().toDouble() - decimalToFraction(formattedResult, precision, tView) + decimalToFraction(resultString, precision, tView) } } @@ -1304,11 +1304,7 @@ class MainActivity : AppCompatActivity() { } // Show result fractions if enabled - if (MyPreferences(this).showResultFraction) { - showFraction = true - } else { - showFraction = false - } + showFraction = MyPreferences(this).showResultFraction // Split the parentheses button (if option is enabled) diff --git a/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt b/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt index f69aee84..ba45004b 100644 --- a/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt +++ b/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt @@ -5,14 +5,22 @@ import android.text.SpannableStringBuilder import android.text.style.RelativeSizeSpan import android.text.style.SuperscriptSpan import android.widget.TextView +import com.darkempire78.opencalculator.calculator.parser.NumberFormatter import kotlin.math.abs import kotlin.math.floor fun decimalToFraction(calculation: String, precision: Double, textView: TextView) { val decimalPosition = calculation.indexOf('.') - var decimal = calculation.substring(decimalPosition).toDouble() - val whole = if (decimalPosition > 0) calculation.substring(0, decimalPosition).toInt() else 0 + val decimal = calculation.substring(decimalPosition).toDouble() + val whole = if (decimalPosition > 0) { + NumberFormatter.format( + calculation.substring(0, decimalPosition), + ".", + "," + ) + + } else "" var n1 = 1 var n2 = 0 @@ -33,7 +41,7 @@ fun decimalToFraction(calculation: String, precision: Double, textView: TextView dec = 1 / (dec - a) } while (abs(dec2 - n1.toDouble() / d1) > dec2 * precision) - if (whole != 0) { + if (whole != "") { if (n1 == 0) { textView.text = whole.toString() } else { diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index dcced70e..bffdfd98 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -89,7 +89,7 @@ 2 3 - 4 + 4 (default) 5 6 7 diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml index 14591636..f9df8650 100644 --- a/app/src/main/res/xml/root_preferences.xml +++ b/app/src/main/res/xml/root_preferences.xml @@ -116,7 +116,7 @@ app:title="@string/settings_fractions_use" app:widgetLayout="@drawable/material_switch" /> Date: Thu, 25 Sep 2025 11:03:56 -0400 Subject: [PATCH 11/13] Corrected issues where live result was not being displayed. --- .../opencalculator/activities/MainActivity.kt | 10 +++++++++- .../darkempire78/opencalculator/calculator/Fraction.kt | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt b/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt index 25c31624..9a948293 100644 --- a/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt +++ b/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt @@ -18,8 +18,8 @@ import android.view.WindowManager import android.view.accessibility.AccessibilityEvent import android.widget.Button import android.widget.HorizontalScrollView -import android.widget.TextView import android.widget.TableRow +import android.widget.TextView import android.widget.Toast import androidx.activity.addCallback import androidx.appcompat.app.AppCompatActivity @@ -655,6 +655,14 @@ class MainActivity : AppCompatActivity() { } } + withContext(Dispatchers.Main) { + if (formattedResult != calculation) { + binding.resultDisplay.text = formattedResult + } else if (!showFraction && !isEqualLastAction){ + binding.resultDisplay.text = "" + } + } + // Save to history if the option autoSaveCalculationWithoutEqualButton is enabled if (MyPreferences(this@MainActivity).autoSaveCalculationWithoutEqualButton) { if (calculation != formattedResult) { diff --git a/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt b/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt index ba45004b..dcc0411e 100644 --- a/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt +++ b/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt @@ -41,7 +41,7 @@ fun decimalToFraction(calculation: String, precision: Double, textView: TextView dec = 1 / (dec - a) } while (abs(dec2 - n1.toDouble() / d1) > dec2 * precision) - if (whole != "") { + if (whole !in " 0") { if (n1 == 0) { textView.text = whole.toString() } else { From cea8738e3f07f59db82ed08b1e363f87b104e1dc Mon Sep 17 00:00:00 2001 From: Bryan Garland Date: Thu, 25 Sep 2025 12:33:00 -0400 Subject: [PATCH 12/13] Updated to show fraction in live result --- .../darkempire78/opencalculator/activities/MainActivity.kt | 6 +++++- .../com/darkempire78/opencalculator/calculator/Fraction.kt | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt b/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt index 892cd288..5d3f2b9c 100644 --- a/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt +++ b/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt @@ -664,7 +664,11 @@ class MainActivity : AppCompatActivity() { withContext(Dispatchers.Main) { if (formattedResult != calculation) { - binding.resultDisplay.text = formattedResult + val tView = findViewById(R.id.resultDisplay) + if (showFraction && '.' in formattedResult) { + val precision = getFractionPrecision().toDouble() + decimalToFraction(formattedResult, precision, tView) + } } else if (!showFraction && !isEqualLastAction){ binding.resultDisplay.text = "" } diff --git a/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt b/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt index dcc0411e..e9fbc245 100644 --- a/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt +++ b/app/src/main/java/com/darkempire78/opencalculator/calculator/Fraction.kt @@ -43,7 +43,7 @@ fun decimalToFraction(calculation: String, precision: Double, textView: TextView if (whole !in " 0") { if (n1 == 0) { - textView.text = whole.toString() + textView.text = whole } else { val tempString = "$whole $n1/$d1" val stringSpan = SpannableStringBuilder(tempString) From beda8db762e9bd29981bd074dbe3351c9e481be3 Mon Sep 17 00:00:00 2001 From: Bryan Garland Date: Thu, 25 Sep 2025 12:34:52 -0400 Subject: [PATCH 13/13] Updated to show fraction in live result --- .../com/darkempire78/opencalculator/activities/MainActivity.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt b/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt index 5d3f2b9c..0553da28 100644 --- a/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt +++ b/app/src/main/java/com/darkempire78/opencalculator/activities/MainActivity.kt @@ -668,6 +668,8 @@ class MainActivity : AppCompatActivity() { if (showFraction && '.' in formattedResult) { val precision = getFractionPrecision().toDouble() decimalToFraction(formattedResult, precision, tView) + } else { + binding.resultDisplay.text = formattedResult } } else if (!showFraction && !isEqualLastAction){ binding.resultDisplay.text = ""