Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
4614299
Add fraction results and precision. Needs tests and tweaking
bmg1919 Jan 23, 2025
1ad34f0
Merge branch 'Darkempire78:main' into fraction-output
bmg1919 Jan 23, 2025
f697067
Merge branch 'Darkempire78:main' into fraction-output
bmg1919 Jan 29, 2025
c72dc66
Moved setting check to onResume()
bmg1919 Jan 29, 2025
8d8c202
Remove unnecessary check
bmg1919 Jan 29, 2025
e898c11
Merge remote-tracking branch 'origin/main' into fraction-output
bmg1919 Apr 18, 2025
ff81790
Change string output to use spannable
bmg1919 Apr 27, 2025
cd93073
Merge branch 'main' into fraction-output
bmg1919 May 11, 2025
3969f74
Moved function to only run when '=' pressed
bmg1919 May 11, 2025
7676ad9
Added icons for fractions and fraction precision
bmg1919 May 12, 2025
bbe1953
Merge branch 'clementwzk:main' into fraction-output
bmg1919 Jul 18, 2025
eff0759
Added fraction tests
bmg1919 Jul 18, 2025
c568e61
Added fraction tests
bmg1919 Jul 18, 2025
84e9170
Garbage cleanup
bmg1919 Jul 18, 2025
1283b43
Fixed default fraction precision and output
bmg1919 Sep 15, 2025
3bfc040
Merge branch 'main' into fraction-output
bmg1919 Sep 21, 2025
d0d3a34
Corrected issues where live result was not being displayed.
bmg1919 Sep 25, 2025
d615fdc
Merge remote-tracking branch 'upstream/main' into fraction-output-v2
bmg1919 Sep 25, 2025
cea8738
Updated to show fraction in live result
bmg1919 Sep 25, 2025
beda8db
Updated to show fraction in live result
bmg1919 Sep 25, 2025
4d3da14
Merge branch 'main' into fraction-output-v2
bmg1919 Oct 31, 2025
ada73a0
Merge remote-tracking branch 'upstream/main' into fraction-output-v2
bmg1919 Nov 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 const val KEY_MOVE_BACK_BUTTON_LEFT = "darkempire78.opencalculator.MOVE_BACK_BUTTON_LEFT"
private const val KEY_NUMBERING_SYSTEM = "darkempire78.opencalculator.NUMBERING_SYSTEM"
private const val KEY_SHOW_ON_LOCK_SCREEN = "darkempire78.opencalculator.KEY_SHOW_ON_LOCK_SCREEN"
Expand Down Expand Up @@ -69,6 +71,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, "1.0E-4")
set(value) = preferences.edit().putString(KEY_FRACTION_PRECISION, value).apply()
var moveBackButtonLeft = preferences.getBoolean(KEY_MOVE_BACK_BUTTON_LEFT, false)
set(value) = preferences.edit().putBoolean(KEY_MOVE_BACK_BUTTON_LEFT, value).apply()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import android.view.accessibility.AccessibilityEvent
import android.widget.Button
import android.widget.HorizontalScrollView
import android.widget.TableRow
import android.widget.TextView
import android.widget.Toast
import androidx.activity.addCallback
import androidx.appcompat.app.AppCompatActivity
Expand All @@ -37,6 +38,7 @@ import com.darkempire78.opencalculator.R
import com.darkempire78.opencalculator.TextSizeAdjuster
import com.darkempire78.opencalculator.Themes
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
Expand Down Expand Up @@ -82,6 +84,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 = ""
Expand Down Expand Up @@ -441,6 +444,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 {
Expand Down Expand Up @@ -656,8 +664,14 @@ class MainActivity : AppCompatActivity() {

withContext(Dispatchers.Main) {
if (formattedResult != calculation) {
binding.resultDisplay.text = formattedResult
} else {
val tView = findViewById<TextView>(R.id.resultDisplay)
if (showFraction && '.' in formattedResult) {
val precision = getFractionPrecision().toDouble()
decimalToFraction(formattedResult, precision, tView)
} else {
binding.resultDisplay.text = formattedResult
}
} else if (!showFraction && !isEqualLastAction){
binding.resultDisplay.text = ""
}
}
Expand Down Expand Up @@ -1051,7 +1065,14 @@ class MainActivity : AppCompatActivity() {
}

// Display result
withContext(Dispatchers.Main) { binding.input.setText(formattedResult) }
withContext(Dispatchers.Main) {
binding.input.setText(formattedResult)
if (showFraction && '.' in formattedResult) {
val tView = findViewById<TextView>(R.id.resultDisplay)
val precision = getFractionPrecision().toDouble()
decimalToFraction(resultString, precision, tView)
}
}

// Set cursor
withContext(Dispatchers.Main) {
Expand All @@ -1062,7 +1083,9 @@ class MainActivity : AppCompatActivity() {
binding.input.isCursorVisible = false

// Clear resultDisplay
binding.resultDisplay.text = ""
if (!showFraction) {
binding.resultDisplay.text = ""
}
}

if (calculation != formattedResult) {
Expand Down Expand Up @@ -1328,6 +1351,10 @@ class MainActivity : AppCompatActivity() {
updateInputDisplay()
}

// Show result fractions if enabled
showFraction = MyPreferences(this).showResultFraction


// Split the parentheses button (if option is enabled)
if (MyPreferences(this).splitParenthesisButton) {
// Hide the AC button
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.darkempire78.opencalculator.calculator

import android.text.Spannable
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('.')
val decimal = calculation.substring(decimalPosition).toDouble()
val whole = if (decimalPosition > 0) {
NumberFormatter.format(
calculation.substring(0, decimalPosition),
".",
","
)

} else ""

var n1 = 1
var n2 = 0
var d1 = 0
var d2 = 1

var dec = decimal // - base.toDouble()
val dec2 = decimal

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 (whole !in " 0") {
if (n1 == 0) {
textView.text = whole
} 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)
textView.text = stringSpan
}
}
9 changes: 9 additions & 0 deletions app/src/main/res/drawable/fracprec.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:pathData="m720,880 l-56,-56 63,-64L480,760v-80h247l-63,-64 56,-56 160,160L720,880ZM80,520v-120h120v120L80,520ZM380,520q-58,0 -99,-41t-41,-99v-160q0,-58 41,-99t99,-41q58,0 99,41t41,99v160q0,58 -41,99t-99,41ZM740,520q-58,0 -99,-41t-41,-99v-160q0,-58 41,-99t99,-41q58,0 99,41t41,99v160q0,58 -41,99t-99,41ZM380,440q25,0 42.5,-17.5T440,380v-160q0,-25 -17.5,-42.5T380,160q-25,0 -42.5,17.5T320,220v160q0,25 17.5,42.5T380,440ZM740,440q25,0 42.5,-17.5T800,380v-160q0,-25 -17.5,-42.5T740,160q-25,0 -42.5,17.5T680,220v160q0,25 17.5,42.5T740,440Z"
android:fillColor="#1f1f1f"/>
</vector>
8 changes: 8 additions & 0 deletions app/src/main/res/drawable/ftfrac.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="60" android:viewportWidth="60" android:width="24dp">

<path android:fillColor="#333333" android:pathData="m11.333,16.946l4.625,-4.983 -2.806,-3.026c-0.679,-0.725 -1.137,-1.218 -1.375,-1.479 -0.229,-0.272 -0.403,-0.538 -0.528,-0.799 -0.125,-0.272 -0.186,-0.578 -0.186,-0.918 0,-0.816 0.264,-1.49 0.798,-2.023 0.531,-0.532 1.134,-0.799 1.802,-0.799 0.647,0 1.155,0.091 1.529,0.272s0.76,0.533 1.158,1.054l2.89,3.621 2.89,-3.621c0.418,-0.521 0.809,-0.873 1.172,-1.054s0.868,-0.272 1.515,-0.272c0.667,0 1.268,0.261 1.802,0.782 0.531,0.521 0.798,1.201 0.798,2.04 0,0.34 -0.061,0.646 -0.186,0.918 -0.125,0.261 -0.308,0.527 -0.545,0.799 -0.226,0.261 -0.679,0.754 -1.358,1.479l-2.806,3.026 4.622,4.983c0.296,0.316 0.545,0.662 0.749,1.036 0.218,0.363 0.325,0.792 0.325,1.291 0,0.827 -0.267,1.497 -0.801,2.008 -0.531,0.499 -1.19,0.746 -1.97,0.746 -0.511,0 -0.931,-0.107 -1.259,-0.322 -0.316,-0.215 -0.702,-0.572 -1.155,-1.071l-3.792,-4.488 -3.792,4.488c-0.395,0.453 -0.769,0.798 -1.12,1.036 -0.354,0.238 -0.783,0.357 -1.294,0.357 -0.78,0 -1.439,-0.247 -1.97,-0.746 -0.534,-0.511 -0.801,-1.181 -0.801,-2.008 0,-0.487 0.09,-0.899 0.273,-1.239 0.191,-0.342 0.458,-0.705 0.798,-1.088z"/>

<path android:fillColor="#333333" android:pathData="m35.093,52.176l1.819,-4.132 -4.622,-11.15c-0.772,-1.793 -1.157,-2.93 -1.157,-3.418 0,-0.76 0.261,-1.372 0.782,-1.837 0.532,-0.464 1.156,-0.696 1.87,-0.696 1.338,0 2.26,0.685 2.771,2.057l3.215,8.382 3.026,-7.483c0.429,-0.995 0.859,-1.738 1.291,-2.225 0.429,-0.487 0.986,-0.731 1.665,-0.731 0.827,0 1.497,0.25 2.008,0.749 0.519,0.487 0.78,1.155 0.78,2.005 0,0.577 -0.221,1.378 -0.662,2.397l-8.043,18.94c-0.386,0.917 -0.766,1.581 -1.14,1.987 -0.363,0.421 -0.966,0.63 -1.816,0.63 -0.873,0 -1.544,-0.267 -2.008,-0.798 -0.453,-0.534 -0.679,-1.085 -0.679,-1.651 0,-0.453 0.055,-0.862 0.168,-1.224 0.125,-0.363 0.368,-0.963 0.731,-1.802z"/>

<path android:fillColor="#00000000" android:pathData="m12.419,36.375l35.38,-20.835" android:strokeColor="#333333" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="5"/>
</vector>
24 changes: 24 additions & 0 deletions app/src/main/res/values/arrays.xml
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,28 @@
<item>1000</item> <!-- Infinity -->
</string-array>

<string-array name="fraction_precision_entries">
<item>2</item>
<item>3</item>
<item>4 (default)</item>
<item>5</item>
<item>6</item>
<item>7</item>
<item>8</item>
<item>9</item>
<item>10</item>
</string-array>

<string-array name="fraction_precision_values">
<item>1.0E-2</item>
<item>1.0E-3</item>
<item>1.0E-4</item>
<item>1.0E-5</item>
<item>1.0E-6</item>
<item>1.0E-7</item>
<item>1.0E-8</item>
<item>1.0E-9</item>
<item>1.0E-10</item>
</string-array>

</resources>
6 changes: 6 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
<string name="settings_category_formatting">FORMATTING</string>
<string name="settings_category_history">HISTORY</string>
<string name="settings_category_advanced">ADVANCED</string>
<string name="settings_category_fractions">FRACTIONS</string>

<string name="settings_general_language">Language</string>

Expand Down Expand Up @@ -122,6 +123,11 @@
<string name="settings_advanced_prevent_sleep">Keep device awake</string>
<string name="settings_advanced_prevent_sleep_desc">Prevent device from sleeping while the app is in the foreground</string>

<string name="settings_fractions_use">Show Fractions</string>
<string name="settings_fractions_use_desc">Display results as fractions as well as decimals</string>
<string name="settings_fractions_precision">Fraction precision</string>
<string name="settings_fractions_precision_desc">How many decimal places before rounding occurs. Anything over will result in fraction rounding</string>

<!-- About page -->
<string name="about_category_help">HELP US</string>
<string name="about_category_social">SOCIAL</string>
Expand Down
19 changes: 19 additions & 0 deletions app/src/main/res/xml/root_preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,25 @@

</PreferenceCategory>

<PreferenceCategory
app:title="@string/settings_category_fractions">

<SwitchPreferenceCompat
app:defaultValue="false"
app:icon="@drawable/ftfrac"
app:key="darkempire78.opencalculator.SHOW_FRACTION"
app:summary="@string/settings_fractions_use_desc"
app:title="@string/settings_fractions_use"
app:widgetLayout="@drawable/material_switch" />
<ListPreference
app:defaultValue="1.0E-4"
app:entries="@array/fraction_precision_entries"
app:entryValues="@array/fraction_precision_values"
app:icon="@drawable/fracprec"
app:key="darkempire78.opencalculator.FRACTION_PRECISION"
app:summary="@string/settings_fractions_precision_desc"
app:title="@string/settings_fractions_precision" />
</PreferenceCategory>
<PreferenceCategory
app:title="@string/settings_category_formatting"
app:color="?attr/text_color">
Expand Down