Skip to content

Commit

Permalink
Merge pull request #262 from kleis-technology/feature/improve-number-…
Browse files Browse the repository at this point in the history
…display

utility class to display a numeric value
  • Loading branch information
pevab authored Jul 25, 2023
2 parents 74da549 + a685a95 commit bb1f688
Show file tree
Hide file tree
Showing 6 changed files with 295 additions and 5 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ dependencies {
val arrowVersion = "1.1.5"
val olcaSimaproVersion = "3.0.5"
val kotlinxSerializationJSONVersion = "1.5.1"

implementation(platform("io.arrow-kt:arrow-stack:$arrowVersion"))
implementation("io.arrow-kt:arrow-core")
implementation("io.arrow-kt:arrow-optics")
Expand Down Expand Up @@ -91,7 +92,6 @@ qodana {
showReport.set(System.getenv("QODANA_SHOW_REPORT")?.toBoolean() ?: false)
}


tasks {
// Set the JVM compatibility versions
properties("javaVersion").let {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package ch.kleis.lcaplugin.ui.toolwindow

import arrow.core.flatten
import arrow.core.replicate
import com.intellij.util.containers.tail
import kotlin.math.*

data class FloatingPointRepresentation(
val isPositive: Boolean,
val digits: List<Int>,
val positionalExponent: Int,
val nbSignificantDigits: Int,
) {
companion object {
fun of(value: Double, nbSignificantDigits: Int = 3): FloatingPointRepresentation {
if (value == 0.0) {
return FloatingPointRepresentation(
true,
IntRange(1, nbSignificantDigits).map { 0 },
0,
nbSignificantDigits
)
}
val isPositive = value > 0.0
val w = abs(value)
val e = ceil(log10(w)).toInt()
val positionalExponent =
if (w == 10.0.pow(e)) e
else e - 1
val shift = nbSignificantDigits - positionalExponent
val reversedDigits = ArrayList<Int>()
var u = floor(w * (10.0.pow(shift))).toInt()
while (u > 0) {
reversedDigits.add(u.mod(10))
u /= 10
}
val digits = reversedDigits.reversed().take(nbSignificantDigits)

if (digits.tail().take(nbSignificantDigits - 1).all { it == 9 }) {
val hd = digits[0]
if (hd == 9) {
val zeros = listOf(0).replicate(nbSignificantDigits - 2).flatten()
return FloatingPointRepresentation(
isPositive,
listOf(1, 0) + zeros,
positionalExponent + 1,
nbSignificantDigits
)
}
val zeros = listOf(0).replicate(nbSignificantDigits - 1).flatten()
return FloatingPointRepresentation(
isPositive,
listOf(hd + 1) + zeros,
positionalExponent,
nbSignificantDigits
)
}
return FloatingPointRepresentation(isPositive, digits, positionalExponent, nbSignificantDigits)
}
}

override fun toString(): String {
return when (positionalExponent) {
in -2..-1 -> {
val hd = listOf(0).replicate(-positionalExponent - 1).flatten()
.joinToString("")
.let { "0.$it" }
val tl = digits.take(nbSignificantDigits - positionalExponent + 1)
.dropLastWhile { it == 0 }
.joinToString("")
val sign = if (isPositive) "" else "-"
"$sign$hd$tl"
}

in 0..2 -> {
val midpoint = min(positionalExponent + 1, nbSignificantDigits)
val hd = digits.subList(0, midpoint)
.joinToString("")
val tl = digits.subList(midpoint, nbSignificantDigits)
.dropLastWhile { it == 0 }
.joinToString("")
.let { if (it.isEmpty()) "" else ".$it" }
val sign = if (isPositive) "" else "-"
"$sign$hd$tl"
}

else -> {
val hd = digits.subList(0, 1)
.joinToString("")
val tl = digits.subList(1, nbSignificantDigits)
.dropLastWhile { it == 0 }
.joinToString("")
.let { if (it.isEmpty()) "" else ".$it" }
val sign = if (isPositive) "" else "-"
val e = "E$positionalExponent"
"$sign$hd$tl$e"
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package ch.kleis.lcaplugin.ui.toolwindow

import ch.kleis.lcaplugin.core.assessment.Inventory
import ch.kleis.lcaplugin.core.lang.value.MatrixColumnIndex
import ch.kleis.lcaplugin.core.matrix.ImpactFactorMatrix
import javax.swing.event.TableModelListener
import javax.swing.table.TableModel

Expand Down Expand Up @@ -59,15 +58,15 @@ class InventoryTableModel(

val quantity = inventory.supply.quantityOf(outputProduct)
if (columnIndex == 1) {
return "${quantity.amount}"
return FloatingPointRepresentation.of(quantity.amount).toString()
}
if (columnIndex == 2) {
return "${quantity.unit.symbol}"
}

val inputProduct = sortedControllablePorts[columnIndex - 3]
val ratio = inventory.impactFactors.valueRatio(outputProduct, inputProduct).amount
return quantity.amount * ratio
return FloatingPointRepresentation.of(quantity.amount * ratio).toString()
}

override fun setValueAt(aValue: Any?, rowIndex: Int, columnIndex: Int) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package ch.kleis.lcaplugin.ui.toolwindow

import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.junit.runners.Parameterized.Parameters


@RunWith(Parameterized::class)
class DisplayedNumberTest(
private val value: Double,
private val expected: String,
) {
companion object {
@Parameters
@JvmStatic
fun getDisplayedStrings(): Collection<Array<Any>> {
return listOf(
arrayOf(0.0, "0"),
arrayOf(0.0001, "1E-4"),
arrayOf(0.001, "1E-3"),
arrayOf(0.01, "0.01"),
arrayOf(0.1, "0.1"),
arrayOf(1.0, "1"),
arrayOf(10.0, "10"),
arrayOf(100.0, "100"),
arrayOf(1000.0, "1E3"),

arrayOf(0.000999, "1E-3"),
arrayOf(0.00999, "0.01"),
arrayOf(0.0999, "0.1"),
arrayOf(0.999, "1"),
arrayOf(9.99, "10"),
arrayOf(99.9, "100"),
arrayOf(999.0, "1E3"),

arrayOf(0.00123, "1.23E-3"),
arrayOf(0.0123, "0.0123"),
arrayOf(0.123, "0.123"),
arrayOf(1.2345, "1.23"),
arrayOf(12.345, "12.3"),
arrayOf(123.45, "123"),
arrayOf(1234.5, "1.23E3"),
arrayOf(12345.123, "1.23E4"),

arrayOf(-0.0, "0"),
arrayOf(-0.00123, "-1.23E-3"),
arrayOf(-0.0123, "-0.0123"),
arrayOf(-0.123, "-0.123"),
arrayOf(-1.2345, "-1.23"),
arrayOf(-12.345, "-12.3"),
arrayOf(-123.45, "-123"),
arrayOf(-1234.5, "-1.23E3"),
arrayOf(-12345.123, "-1.23E4"),
)
}
}

@Test
fun run() {
// when
val actual = FloatingPointRepresentation.of(value).toString()

// then
assertEquals(expected, actual)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package ch.kleis.lcaplugin.ui.toolwindow

import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.junit.runners.Parameterized.Parameters
import org.junit.Test
import kotlin.test.assertEquals

private fun digits(s: String): List<Int> {
return s.map { Integer.parseInt(it.toString()) }
}

@RunWith(Parameterized::class)
class FloatingPointRepresentationTest(
private val value: Double,
private val expected: FloatingPointRepresentation,
) {
companion object {

@Parameters
@JvmStatic
fun getFloatingPointRepresentationSamples(): Collection<Array<Any>> {
return listOf(
arrayOf(0.0012345, FloatingPointRepresentation(true, digits("123"), -3, 3)),
arrayOf(0.012345, FloatingPointRepresentation(true, digits("123"), -2, 3)),
arrayOf(0.12345, FloatingPointRepresentation(true, digits("123"), -1, 3)),
arrayOf(1.2345, FloatingPointRepresentation(true, digits("123"), 0, 3)),
arrayOf(12.345, FloatingPointRepresentation(true, digits("123"), 1, 3)),
arrayOf(123.45, FloatingPointRepresentation(true, digits("123"), 2, 3)),
arrayOf(1234.5, FloatingPointRepresentation(true, digits("123"), 3, 3)),
arrayOf(12345.0, FloatingPointRepresentation(true, digits("123"), 4, 3)),

arrayOf(0.0, FloatingPointRepresentation(true, digits("000"), 0, 3)),
arrayOf(0.0001, FloatingPointRepresentation(true, digits("100"), -4, 3)),
arrayOf(0.001, FloatingPointRepresentation(true, digits("100"), -3, 3)),
arrayOf(0.01, FloatingPointRepresentation(true, digits("100"), -2, 3)),
arrayOf(0.1, FloatingPointRepresentation(true, digits("100"), -1, 3)),
arrayOf(1.0, FloatingPointRepresentation(true, digits("100"), 0, 3)),
arrayOf(10.0, FloatingPointRepresentation(true, digits("100"), 1, 3)),
arrayOf(100.0, FloatingPointRepresentation(true, digits("100"), 2, 3)),
arrayOf(1000.0, FloatingPointRepresentation(true, digits("100"), 3, 3)),

arrayOf(0.000999, FloatingPointRepresentation(true, digits("100"), -3, 3)),
arrayOf(0.00999, FloatingPointRepresentation(true, digits("100"), -2, 3)),
arrayOf(0.0999, FloatingPointRepresentation(true, digits("100"), -1, 3)),
arrayOf(0.999, FloatingPointRepresentation(true, digits("100"), 0, 3)),
arrayOf(9.99, FloatingPointRepresentation(true, digits("100"), 1, 3)),
arrayOf(99.9, FloatingPointRepresentation(true, digits("100"), 2, 3)),
arrayOf(999.0, FloatingPointRepresentation(true, digits("100"), 3, 3)),

arrayOf(0.001001, FloatingPointRepresentation(true, digits("100"), -3, 3)),
arrayOf(0.01001, FloatingPointRepresentation(true, digits("100"), -2, 3)),
arrayOf(0.1001, FloatingPointRepresentation(true, digits("100"), -1, 3)),
arrayOf(1.001, FloatingPointRepresentation(true, digits("100"), 0, 3)),
arrayOf(10.01, FloatingPointRepresentation(true, digits("100"), 1, 3)),
arrayOf(100.1, FloatingPointRepresentation(true, digits("100"), 2, 3)),
arrayOf(1001.0, FloatingPointRepresentation(true, digits("100"), 3, 3)),

arrayOf(0.0002999, FloatingPointRepresentation(true, digits("300"), -4, 3)),
arrayOf(0.003999, FloatingPointRepresentation(true, digits("400"), -3, 3)),
arrayOf(0.04999, FloatingPointRepresentation(true, digits("500"), -2, 3)),
arrayOf(0.5999, FloatingPointRepresentation(true, digits("600"), -1, 3)),
arrayOf(6.999, FloatingPointRepresentation(true, digits("700"), 0, 3)),
arrayOf(79.99, FloatingPointRepresentation(true, digits("800"), 1, 3)),
arrayOf(899.9, FloatingPointRepresentation(true, digits("900"), 2, 3)),

arrayOf(-0.0012345, FloatingPointRepresentation(false, digits("123"), -3, 3)),
arrayOf(-0.012345, FloatingPointRepresentation(false, digits("123"), -2, 3)),
arrayOf(-0.12345, FloatingPointRepresentation(false, digits("123"), -1, 3)),
arrayOf(-1.2345, FloatingPointRepresentation(false, digits("123"), 0, 3)),
arrayOf(-12.345, FloatingPointRepresentation(false, digits("123"), 1, 3)),
arrayOf(-123.45, FloatingPointRepresentation(false, digits("123"), 2, 3)),
arrayOf(-1234.5, FloatingPointRepresentation(false, digits("123"), 3, 3)),
arrayOf(-12345.0, FloatingPointRepresentation(false, digits("123"), 4, 3)),

arrayOf(-0.0, FloatingPointRepresentation(true, digits("000"), 0, 3)),
arrayOf(-0.0001, FloatingPointRepresentation(false, digits("100"), -4, 3)),
arrayOf(-0.001, FloatingPointRepresentation(false, digits("100"), -3, 3)),
arrayOf(-0.01, FloatingPointRepresentation(false, digits("100"), -2, 3)),
arrayOf(-0.1, FloatingPointRepresentation(false, digits("100"), -1, 3)),
arrayOf(-1.0, FloatingPointRepresentation(false, digits("100"), 0, 3)),
arrayOf(-10.0, FloatingPointRepresentation(false, digits("100"), 1, 3)),
arrayOf(-100.0, FloatingPointRepresentation(false, digits("100"), 2, 3)),
arrayOf(-1000.0, FloatingPointRepresentation(false, digits("100"), 3, 3)),

arrayOf(-0.000999, FloatingPointRepresentation(false, digits("100"), -3, 3)),
arrayOf(-0.00999, FloatingPointRepresentation(false, digits("100"), -2, 3)),
arrayOf(-0.0999, FloatingPointRepresentation(false, digits("100"), -1, 3)),
arrayOf(-0.999, FloatingPointRepresentation(false, digits("100"), 0, 3)),
arrayOf(-9.99, FloatingPointRepresentation(false, digits("100"), 1, 3)),
arrayOf(-99.9, FloatingPointRepresentation(false, digits("100"), 2, 3)),
arrayOf(-999.0, FloatingPointRepresentation(false, digits("100"), 3, 3)),

arrayOf(-0.001001, FloatingPointRepresentation(false, digits("100"), -3, 3)),
arrayOf(-0.01001, FloatingPointRepresentation(false, digits("100"), -2, 3)),
arrayOf(-0.1001, FloatingPointRepresentation(false, digits("100"), -1, 3)),
arrayOf(-1.001, FloatingPointRepresentation(false, digits("100"), 0, 3)),
arrayOf(-10.01, FloatingPointRepresentation(false, digits("100"), 1, 3)),
arrayOf(-100.1, FloatingPointRepresentation(false, digits("100"), 2, 3)),
arrayOf(-1001.0, FloatingPointRepresentation(false, digits("100"), 3, 3)),

arrayOf(-0.0002999, FloatingPointRepresentation(false, digits("300"), -4, 3)),
arrayOf(-0.003999, FloatingPointRepresentation(false, digits("400"), -3, 3)),
arrayOf(-0.04999, FloatingPointRepresentation(false, digits("500"), -2, 3)),
arrayOf(-0.5999, FloatingPointRepresentation(false, digits("600"), -1, 3)),
arrayOf(-6.999, FloatingPointRepresentation(false, digits("700"), 0, 3)),
arrayOf(-79.99, FloatingPointRepresentation(false, digits("800"), 1, 3)),
arrayOf(-899.9, FloatingPointRepresentation(false, digits("900"), 2, 3)),
)
}

}

@Test
fun run() {
// when
val actual = FloatingPointRepresentation.of(value, 3)

// then
assertEquals(expected, actual, "value = $value")
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class LcaProcessAssessResultTest {
assertThat(html, containsString("<td>carrot</td>"))
val text = result.getTransferData(DataFlavor("text/plain;class=java.lang.String")) as String
assertThat(text, containsString("item\tquantity\tunit\t[Resource] propanol(air) [kg]"))
assertThat(text, containsString("\ncarrot\t1.0\tg\t0.001\t"))
assertThat(text, containsString("\ncarrot\t1\tg\t1E-3\t"))
}

}

0 comments on commit bb1f688

Please sign in to comment.