Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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_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 @@ -68,6 +70,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()
var numberingSystem = preferences.getInt(KEY_NUMBERING_SYSTEM, 0)
set(value) = preferences.edit().putInt(KEY_NUMBERING_SYSTEM, value).apply()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ 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
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
Expand All @@ -34,6 +34,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 @@ -79,6 +80,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 @@ -431,6 +433,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 @@ -644,14 +651,6 @@ class MainActivity : AppCompatActivity() {
}
}

withContext(Dispatchers.Main) {
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) {
Expand Down Expand Up @@ -1041,7 +1040,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(formattedResult, precision, tView)
}
}

// Set cursor
withContext(Dispatchers.Main) {
Expand All @@ -1052,7 +1058,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 @@ -1295,6 +1303,14 @@ class MainActivity : AppCompatActivity() {
updateInputDisplay()
}

// 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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
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 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

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 != 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)
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</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 @@ -105,6 +105,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="2"
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