ImpreciseFraction. Dear... god. There's more. Noooo!
This commit is contained in:
parent
3313a3d011
commit
a859084b6f
@ -68,7 +68,7 @@ private fun bytesToLongBE(
|
||||
)
|
||||
}
|
||||
|
||||
const val EPSILON = 0.0000001
|
||||
const val EPSILON = 0.0000000000001
|
||||
|
||||
private fun cmpDouble(a: Double, b: Double): Boolean {
|
||||
if (a == b)
|
||||
@ -89,6 +89,12 @@ private val BI_DOUBLE_MIN = BigDecimal(Double.MIN_VALUE.toString()).toBigInteger
|
||||
|
||||
private val PERCENTAGE_CONTEXT = MathContext(6)
|
||||
|
||||
private const val MEANINGFUL_BITS = 16
|
||||
private const val MEANINGFUL_BITS_LONG = 1000000000000000000L
|
||||
private const val MEANINGFUL_BITS_DOUBLE = MEANINGFUL_BITS_LONG.toDouble()
|
||||
private val MEANINGFUL_BITS_CONTEXT = MathContext(MEANINGFUL_BITS)
|
||||
private val MEANINGFUL_BITS_BI = BigInteger.valueOf(MEANINGFUL_BITS_LONG)
|
||||
|
||||
@Suppress("unused")
|
||||
class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Double = 0.0) : Comparable<ImpreciseFraction> {
|
||||
@JvmOverloads constructor(whole: Byte, decimal: Double = 0.0) : this(BigInteger.valueOf(whole.toLong()), decimal)
|
||||
@ -151,22 +157,61 @@ class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Do
|
||||
val a = whole
|
||||
val c = other.whole
|
||||
|
||||
val b = 1.0 / decimal
|
||||
val d = 1.0 / other.decimal
|
||||
val bZero = cmpDouble(decimal, 0.0)
|
||||
val dZero = cmpDouble(other.decimal, 0.0)
|
||||
|
||||
if (bZero && dZero) {
|
||||
if (isZero(a) || isZero(c))
|
||||
return this
|
||||
|
||||
return ImpreciseFraction(a * c)
|
||||
} else if (bZero) {
|
||||
val d = other.decimal * MEANINGFUL_BITS_DOUBLE
|
||||
val dL = d.toLong()
|
||||
val adInflated = a * BigInteger.valueOf(dL)
|
||||
val ad = adInflated.divideAndRemainder(MEANINGFUL_BITS_BI)
|
||||
|
||||
return ImpreciseFraction(
|
||||
a * c + ad[0],
|
||||
ad[1].toDouble() / MEANINGFUL_BITS_DOUBLE
|
||||
)
|
||||
} else if (dZero) {
|
||||
val b = decimal * MEANINGFUL_BITS_DOUBLE
|
||||
val bL = b.toLong()
|
||||
val bcInflated = c * BigInteger.valueOf(bL)
|
||||
val bc = bcInflated.divideAndRemainder(MEANINGFUL_BITS_BI)
|
||||
|
||||
return ImpreciseFraction(
|
||||
a * c + bc[0],
|
||||
bc[1].toDouble() / b
|
||||
)
|
||||
}
|
||||
|
||||
val b = decimal * MEANINGFUL_BITS_DOUBLE
|
||||
val d = other.decimal * MEANINGFUL_BITS_DOUBLE
|
||||
|
||||
val bL = b.toLong()
|
||||
val dL = d.toLong()
|
||||
|
||||
val bc = c.divideAndRemainder(BigInteger.valueOf(bL))
|
||||
val ad = a.divideAndRemainder(BigInteger.valueOf(dL))
|
||||
val bcInflated = c * BigInteger.valueOf(bL)
|
||||
val adInflated = a * BigInteger.valueOf(dL)
|
||||
|
||||
val bc = bcInflated.divideAndRemainder(MEANINGFUL_BITS_BI)
|
||||
val ad = adInflated.divideAndRemainder(MEANINGFUL_BITS_BI)
|
||||
|
||||
return ImpreciseFraction(
|
||||
a * c + bc[0] + ad[0],
|
||||
decimal * other.decimal + bc[1].toDouble() / b + ad[1].toDouble() / d
|
||||
decimal * other.decimal + bc[1].toDouble() / MEANINGFUL_BITS_DOUBLE + ad[1].toDouble() / MEANINGFUL_BITS_DOUBLE
|
||||
)
|
||||
}
|
||||
|
||||
operator fun div(other: ImpreciseFraction): ImpreciseFraction {
|
||||
if (isZero && other.isZero)
|
||||
return this
|
||||
|
||||
if (isZero(whole) && isZero(other.whole))
|
||||
return ImpreciseFraction(BigInteger.ZERO, decimal / other.decimal)
|
||||
|
||||
val a = toBigDecmial()
|
||||
val b = other.toBigDecmial()
|
||||
val div = a.divideAndRemainder(b, MathContext(a.precision() + b.precision()))
|
||||
@ -240,7 +285,7 @@ class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Do
|
||||
if (decimals == 0) {
|
||||
return whole.toString()
|
||||
} else if (decimals > 0) {
|
||||
val strDecimal = if (decimal == 0.0 || decimal == -0.0) {
|
||||
val strDecimal = if (decimal == 0.0 || decimal == -0.0 || decimal > 0.0 && decimal < 1E-11 || decimal < 0.0 && decimal > -1E-11) {
|
||||
"0"
|
||||
} else if (decimal > 0.0) {
|
||||
decimal.toString().substring(2)
|
||||
|
Loading…
Reference in New Issue
Block a user