Kotlin มีวิธีอรรถประโยชน์ BigDecimal setPrecision หรือไม่

ฉันอ่านเจอบางที่ที่คณะกรรมการตัดสินของ Java ตัดสินใจว่าเมธอด setPrecision บน BigDecimal คงจะโง่มาก เนื่องจากมี setScale อยู่แล้ว

สิ่งที่โง่กว่านั้นคือการที่ผู้ใช้ API มีวิธีการเช่นนี้ในโค้ดของพวกเขา:

private fun getBigDecimalWith16DigitPrecision(value: BigDecimal): BigDecimal {
    return when {
        value < BigDecimal.ONE -> value.setScale(16, RoundingMode.HALF_UP)
        value < BigDecimal(10) -> value.setScale(15, RoundingMode.HALF_UP)
        value < BigDecimal(100) -> value.setScale(14, RoundingMode.HALF_UP)
        value < BigDecimal(1000) -> value.setScale(13, RoundingMode.HALF_UP)
        value < BigDecimal(10000) -> value.setScale(12, RoundingMode.HALF_UP)
        else -> value.setScale(11, RoundingMode.HALF_UP)
    }
}

ซึ่งไม่ได้ครอบคลุมทุกกรณีด้วยซ้ำ


person Torben Vesterager    schedule 21.01.2020    source แหล่งที่มา
comment
ดังที่ฉันเห็นแล้วว่าคณะกรรมการ Java เป็นหนี้ฉันสำหรับโค้ดประมาณ 10 บรรทัด ซึ่งตอนนี้ฉันต้องลบออกจากจำนวนทั้งหมด ของเส้นที่ฉันสามารถรักษาได้อย่างมีประสิทธิภาพ   -  person Torben Vesterager    schedule 21.01.2020
comment
จะเป็นอย่างไรถ้า BigDecimal มีเมธอด setPrecision ไม่ได้รับมัน.   -  person ernest_k    schedule 21.01.2020
comment
ฉันเดาว่านี่เป็นตัวอย่างที่ค่อนข้างหายาก   -  person Dorian Gray    schedule 21.01.2020
comment
@ernest_k เช่น BigDecimal("33.23").setPrecision(5) == BigDecimal("33.230"), BigDecimal("33.23").setPrecision(2) == BigDecimal("33").   -  person Alexey Romanov    schedule 21.01.2020


คำตอบ (2)


เป็นเพียงบรรทัดเดียว เนื่องจากสเกลของคุณจำเป็นต้องเปลี่ยนแปลงมากพอๆ กับความแม่นยำ:

fun BigDecimal.setPrecision(newPrecision: Int) = setScale(scale() + (newPrecision - precision()), RoundingMode.HALF_UP)

หรืออีกทางหนึ่ง (ชัดเจนกว่า แต่มีประสิทธิภาพน้อยกว่า):

fun BigDecimal.setPrecision(newPrecision: Int) = BigDecimal(toPlainString(), MathContext(newPrecision, RoundingMode.HALF_UP))
person Alexey Romanov    schedule 21.01.2020

หากสิ่งที่คุณกำลังมองหาคือโค้ดเวอร์ชันที่เรียบง่ายกว่า (กระชับกว่า) คุณสามารถทำให้มันง่ายขึ้นได้โดยการคำนวณมาตราส่วน (16 - log10(value) หรือ 11 แล้วแต่จำนวนใดจะมากกว่า):

return value.setScale((int) Math.max(11, 16 - Math.log10(value.doubleValue())),
                      RoundingMode.HALF_UP);
person ernest_k    schedule 21.01.2020