Kotlin大小数除法返回不准确的结果



我正在与Kotlin和android studio一起构建一个计算器(我的第一个项目(。在最近对十进制格式进行调整之前,所有方程都能正常工作。现在,大型除法运算返回不准确的结果。

例如99999999/9%(0.09(=1.111111110000E9但9%/999999999=0,而它应该=9.0000000009E-10

这是因为当前DecimalFormat无法返回负指数吗?

编辑:经过更多的测试,我发现将划分方法改为

doubleNum = doubleNum.divide(numBigDecimal, 10, BigDecimal.ROUND_HALF_UP).stripTrailingZeros()

运行相同的等式将在格式化之前返回9E-10。在十进制格式之后,结果显示为""只有没有数字的

// enum class and class properties
enum class LogicTypes {
None,Add,Subtract,Multiply,Divide
}
class MainActivity : AppCompatActivity() {
private var logicActive = false
private var currentLogic = LogicTypes.None
private var currentNum = BigDecimal.ZERO
private var displayNum = ""
private var memoryNum = BigDecimal.ZERO
// add num function - buttons 0-9 send indices to num arg
fun addNum(num: BigDecimal) {
val inputNum = num.toString()
if (displayNum == "0" && inputNum == "0") {
return
}
if (displayNum.contains(".")) {
val stringForm = displayNum.substring(displayNum.indexOf('.'), displayNum.length)
if (stringForm.length > 10) {
clearCalc()
Toast.makeText(this, "Only 10 digits after decimal point allowed.", Toast.LENGTH_SHORT).show()
return
}
}
if (displayNum.length >= 15 && !displayNum.contains(".")) {
clearCalc()
Toast.makeText(this, "Maximum of 15 digits allowed.", Toast.LENGTH_SHORT).show()
return
}
if (inputNum == "0" && currentNum.toDouble() == 0.0 && displayNum.contains(".")) {
if (displayNum.length > 11) {
clearCalc()
Toast.makeText(this, "Only 10 digits after decimal point allowed.", Toast.LENGTH_SHORT).show()
return
}
displayNum = "$displayNum$inputNum"
textView.text = displayNum
return
}
if (logicActive) {
logicActive = false
displayNum = "0"
}
displayNum = "$displayNum$inputNum"
updateDisplayNum()
}
// set currentNum and send to numFormat function to update textView
fun updateDisplayNum() {
if (currentNum.toString().length > 15) {
clearCalc()
Toast.makeText(this, "Maximum of 15 digits allowed.", Toast.LENGTH_SHORT).show()
return
}
val numBigDecimal = displayNum.toBigDecimal()
if(currentLogic == LogicTypes.None) {
if(displayNum.contains("-") && currentNum == BigDecimal.ZERO) {
textView.text = displayNum
return
} else {
currentNum = numBigDecimal
}
}
numFormat()
}
// format decimal and integers and update textview with exponent
fun numFormat() {
val numBigDecimal = displayNum.toBigDecimal()
if(displayNum.contains(".")) {
val stringForm = displayNum.substring(displayNum.indexOf('.'), displayNum.length)
var numFormat = "#,##0."
if(stringForm.length > 1) {
for (num in stringForm.indices-1) {
numFormat += "0"
}
}
if (displayNum.length > 16 || stringForm.length > 9) {
// stringform length > 9 works for division result - anything higher returns trailing zeros.
// anything under 11 for stringform condition results in inaccurate input -
// adding decimal through addNum() will return Exponential notation before logic
// I only want E notation on result only- have yet to test other equations - 
// this can also make it impossible to take the result and conduct another logic operation as the result appends E0 
// and thus the trailing digits after decimal is greater than 10
numFormat = "0.0000000000E0"
}
val df = DecimalFormat(numFormat)
textView.text = df.format(numBigDecimal)
return
}
var df = DecimalFormat("#,###")
if (displayNum.length > 15) {
df = DecimalFormat("0.0000000000E0")
}
textView.text = df.format(numBigDecimal)
}
// change logic to enum mode when button operator pressed
fun changeLogic(mode: LogicTypes) {
currentLogic = mode
logicActive = true
}
// calculate function
fun calculate() {
if (logicActive || currentLogic == LogicTypes.Divide && displayNum.toBigDecimal() == BigDecimal.ZERO
|| currentNum == BigDecimal.ZERO) {
Log.i(LOG_TAG, "caught the zero")
return
}
val numBigDecimal = displayNum.toBigDecimal()
var doubleNum = currentNum

val currentNumString = doubleNum.stripTrailingZeros().toPlainString()
val numBigDecimalString = numBigDecimal.stripTrailingZeros().toPlainString()
val addMsg = getString(R.string.calc_message, currentNumString, "+", numBigDecimalString)
val subMsg = getString(R.string.calc_message, currentNumString, "-", numBigDecimalString)
val multiMsg = getString(R.string.calc_message, currentNumString, "*", numBigDecimalString)
val divMsg = getString(R.string.calc_message, currentNumString, "/", numBigDecimalString)

when(currentLogic) {
LogicTypes.Add -> {
hintView.text = addMsg
doubleNum += numBigDecimal
doubleNum = doubleNum.stripTrailingZeros()
}
LogicTypes.Subtract -> {
hintView.text = subMsg
doubleNum -= numBigDecimal
doubleNum = doubleNum.stripTrailingZeros()
}
LogicTypes.Multiply -> {
hintView.text = multiMsg
doubleNum *= numBigDecimal
doubleNum = doubleNum.stripTrailingZeros()
}
LogicTypes.Divide -> {
hintView.text = divMsg
doubleNum /= numBigDecimal
doubleNum = doubleNum.stripTrailingZeros()
}
LogicTypes.None -> return
}
currentLogic = LogicTypes.None
displayNum = doubleNum.toString()
updateDisplayNum()
logicActive = true
}

好的,问题是我在计算函数中使用了这个。

displayNum = doubleNum.toString()

更改为.toPlainString((可以给出正确的符号。格式化仍然有问题,但我会看看我是否可以在自己的上解决这些问题

EDIT:我通过创建一个布尔属性,在计算函数中将其设置为true,并将其传递给numFormat条件来解决numFormat中的格式化问题:

if (displayNum.length > 16 || stringForm.length > 9 && resultActive) {
numFormat = "0.0000000000E0"
resultActive = false
}

这样,格式只适用于计算的数字

我还将其传递给addNum函数,用于在第一次计算后进行的计算

if(resultActive) {
resultActive = false
}