Skip to content

Commit ea56baf

Browse files
committed
Implement a class for representing decimal fractions
Will be useful for representing the state of fractions of second internally.
1 parent d58a4aa commit ea56baf

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed

core/common/src/internal/math.kt

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,3 +179,62 @@ internal fun multiplyAndAdd(d: Long, n: Long, r: Long): Long {
179179
}
180180
return safeAdd(safeMultiply(md, n), mr)
181181
}
182+
183+
internal val POWERS_OF_TEN = intArrayOf(
184+
1,
185+
10,
186+
100,
187+
1000,
188+
10000,
189+
100000,
190+
1000000,
191+
10000000,
192+
100000000,
193+
1000000000
194+
)
195+
196+
/**
197+
* The fraction [fractionalPart]/10^[digits].
198+
*/
199+
internal class DecimalFraction(
200+
/**
201+
* The numerator of the fraction.
202+
*/
203+
val fractionalPart: Int,
204+
/**
205+
* The number of digits after the decimal point.
206+
*/
207+
val digits: Int
208+
): Comparable<DecimalFraction> {
209+
init {
210+
require(digits >= 0) { "Digits must be non-negative, but was $digits" }
211+
}
212+
213+
/**
214+
* The integral numerator of the fraction, but with [newDigits] digits after the decimal point.
215+
* The rounding is done using the towards-zero rounding mode.
216+
*/
217+
fun fractionalPartWithNDigits(newDigits: Int): Int = when {
218+
newDigits == digits -> fractionalPart
219+
newDigits > digits -> fractionalPart * POWERS_OF_TEN[newDigits - digits]
220+
else -> fractionalPart / POWERS_OF_TEN[digits - newDigits]
221+
}
222+
223+
override fun compareTo(other: DecimalFraction): Int =
224+
maxOf(digits, other.digits).let { maxPrecision ->
225+
fractionalPartWithNDigits(maxPrecision).compareTo(other.fractionalPartWithNDigits(maxPrecision))
226+
}
227+
228+
override fun equals(other: Any?): Boolean = other is DecimalFraction && compareTo(other) == 0
229+
230+
override fun toString(): String = buildString {
231+
val denominator = POWERS_OF_TEN[digits]
232+
append(fractionalPart / denominator)
233+
append('.')
234+
append((denominator + (fractionalPart % denominator)).toString().removePrefix("1"))
235+
}
236+
237+
override fun hashCode(): Int {
238+
throw UnsupportedOperationException("DecimalFraction is not supposed to be used as a hash key")
239+
}
240+
}

0 commit comments

Comments
 (0)