【问题标题】:I can't get the part of the code that is creating the problem我无法获得导致问题的代码部分
【发布时间】:2020-07-01 16:46:24
【问题描述】:

我正在制作一个分数计算器,最终确定了设计和工作原理,并编写了代码。但是,它几乎从不给出正确答案。我不知道为什么会这样?

它使用我创建的 Fraction 类,它只包含 3 个变量:分子、分母和整数。

该过程涉及以下内容:

从用户那里获取输入并转换为分数形式

计算

简化结果

最后显示结果。

代码:

package com.example.fraccalcinkotlin

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.widget.Toast
import androidx.core.text.isDigitsOnly
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        editText_number1_num.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(s: Editable) {}
            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence, start: Int,
                                       before: Int, count: Int) {
                if (s.endsWith(" ")){
                    editText_number1_den.requestFocus()
                    editText_number1_num.setText(removeLastChar(editText_number1_num.text.toString()))
                }
            }
        })
        editText_number1_den.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(s: Editable) {}
            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence, start: Int,
                                       before: Int, count: Int) {
                if (s.endsWith(" ") || s.endsWith("/")){
                    editText_number1_den.setText(removeLastChar(editText_number1_den.text.toString()))
                }
            }
        })
        editText_number1_whole.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(s: Editable) {}
            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                if (s.endsWith(" ")){
                    editText_number1_num.requestFocus()
                    editText_number1_whole.setText(removeLastChar(editText_number1_whole.text.toString()))
                }
            }
        })


        editText_number2_num.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(s: Editable) {}
            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                if (s.endsWith(" ")){
                    editText_number2_den.requestFocus()
                    editText_number2_num.setText(removeLastChar(editText_number2_num.text.toString()))
                }
            }
        })
        editText_number2_den.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(s: Editable) {}
            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                if (s.endsWith(" ") || s.endsWith("/")){
                    editText_number2_den.setText(removeLastChar(editText_number2_den.text.toString()))
                }
            }
        })
        editText_number2_whole.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(s: Editable) {}
            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                if (s.endsWith(" ")){
                    editText_number2_num.requestFocus()
                    editText_number2_whole.setText(removeLastChar(editText_number2_whole.text.toString()))
                }
            }
        })
        button_add.setOnClickListener {
            var sum:Fraction = AddNumbers()
            var num: Int = sum.numerator
            var den: Int = sum.denominator
            var whole: Int = sum.wholeNo
            var result_string: String = "$whole $num/$den"
            textView_result.text = result_string
        }
    }
    fun AddNumbers(): Fraction {
        //convert String to Fraction for calculations
        val num1: Int = editText_number1_num.text.toString().toInt()
        val den1: Int = editText_number1_den.text.toString().toInt()
        val whole1: Int = editText_number1_whole.text.toString().toInt()
        val fraction1: List<Int> = listOf(num1, den1, whole1)
        val num2: Int = editText_number2_num.text.toString().toInt()
        val den2: Int = editText_number2_den.text.toString().toInt()
        val whole2: Int = editText_number2_whole.text.toString().toInt()
        val fraction2: List<Int> = listOf(num2, den2, whole2)
        var frac_1: Fraction = fractionalize(fraction1)
        var frac_2: Fraction = fractionalize(fraction2)
        //extracting numerators and denominators from List<Int>
        var numerator1 = frac_1.numerator
        var denominator1 = frac_1.denominator
        var numerator2 = frac_2.numerator
        var denominator2 = frac_2.denominator
        //Getting common denominator and numerators for adding
        var commonDenominator: Int = 1
        if (denominator1 != denominator2){
            commonDenominator = getLCM(denominator1, denominator2)
            numerator1 *= commonDenominator/denominator1
            numerator2 *= commonDenominator/denominator2
        } else if (denominator1 == denominator2){
            commonDenominator = denominator1
        }
        //adding....
        var sumOfNumerators: Int = numerator1 + numerator2
        var result: Fraction = Fraction(sumOfNumerators, commonDenominator,0)
        //simplifying....
        result = simplify(result)
        return frac_1
    }
    fun fractionalize(fraction: List<Int>): Fraction{
        //Finds type of number (input) and converts to List<Int> with [numerator, denominator, whole number]
        var num = fraction[0]
        var den = fraction[1]
        var whole = fraction[2]
        if (whole != 0){
            num += whole * den
            whole = 0
        }
        val result: Fraction = Fraction(num, den, whole)
        return result
    }
    fun simplify(fraction:Fraction):Fraction{
        var numerator: Int = fraction.numerator
        var denominator: Int = fraction.denominator
        var whole_number: Int = fraction.wholeNo
        if (getHCF(numerator, denominator) != 1){
            numerator /= getHCF(numerator, denominator)
            denominator /= getHCF(numerator, denominator)
        }

        if (numerator> denominator){
            numerator %= denominator
            whole_number = numerator / denominator
        }
        if (numerator == denominator){
            whole_number += 1
            numerator = 0
            denominator = 1
        }
        var result: Fraction = Fraction(numerator, denominator, whole_number)
        return result
    }
    fun getHCF(num1: Int, num2: Int):Int{
        var dividend = Math.max(num1, num2)
        var divisor = Math.min(num1, num2)
        var remainder: Int = 1
        //calculating HCF using repeated division method
        do {
            remainder = dividend % divisor
            dividend = divisor
            divisor = remainder
        } while (remainder > 0)
        return dividend
    }
    fun getLCM(num1: Int, num2: Int): Int{
        //num1 * num2 = HCF * LCM
        //so, LCM = (num1 * num2) / HCF
        var result: Int = (num1 * num2)/getHCF(num1, num2)
        return result
    }
    fun removeLastChar(string: String): String{
        var result: String = string
        if (!string.isEmpty()){
            result = string.substring(0, string.length - 1);
        }
        return  result
    }

}

请建议我可以做些什么来找出导致问题的部分。

【问题讨论】:

  • removeLastChar 是一个不必要的功能。您可以使用现有的String.dropLast(1)
  • 哦...我问了另一个关于如何删除最后一个字符的问题,用户回复了代码。谢谢!

标签: android android-studio debugging kotlin


【解决方案1】:

我想我在simplify 中看到了错误:

    if (numerator> denominator){
        numerator %= denominator
        whole_number = numerator / denominator
    }

您已经将numerator 变量更改为余数,然后使用它来查找整数。您需要在if 语句中交换这两行的顺序。

最好让 Fraction 上的所有这些操作成为 Fraction 类本身的一部分。这称为封装,是稳健软件设计的基础。错误将更少且更容易解决。像这样的东西(我没有测试数学):

data class Fraction(val num: Int, val den: Int, val whole: Int) {
    fun toPure(): Fraction {
        return Fraction(num + whole * den, den, 0)
    }

    fun toSimplified(withWhole: Boolean): Fraction {
        with(toPure()) {
            val gcm = findGcf(num, den)
            val simplified = Fraction(num / gcm, den / gcm, 0)
            return if (!withWhole || num < den)
                simplified
            else
                Fraction(simplified.num % simplified.den, simplified.den, simplified.num / simplified.den)
        }
    }

    operator fun plus(other: Fraction): Fraction {
        val newDen = den * other.den
        val newNum = num * other.den + other.num * den
        return Fraction(newNum, newDen, whole + other.whole).toSimplified(true)
    }

    private fun findGcf(num1: Int, num2: Int): Int {
        var dividend = max(num1, num2)
        var divisor = min(num1, num2)
        var remainder: Int = 1
        //calculating HCF using repeated division method
        do {
            remainder = dividend % divisor
            dividend = divisor
            divisor = remainder
        } while (remainder > 0)
        return dividend
    }
}

为避免重复自己,您可以创建一个用于将 EditText 内容转换为 Fraction 的函数:

private fun getFraction(numET: EditText, denET: EditText, wholeET: EditText): Fraction? {
    val num = numET.text.toIntOrNull() ?: return null
    val den = denET.text.toIntOrNull() ?: return null
    val whole = wholeT.text.toIntOrNull() ?: return null
    return Fraction(num, den, whole)
}

那么你的addNumbers函数就简单多了:

fun addNumbers(): Fraction? {
    val first = getFraction(editText_number1_num, editText_number1_den, editText_number1_whole) ?: return null
    val second = getFraction(editText_number2_num, editText_number2_den, editText_number2_whole) ?: return null
    return first + second
}

在输入无效的情况下,我使返回类型可以为空。如果输入无效,使用 addNumbers 的点击监听器会显示错误消息而不是 Fraction。

【讨论】:

  • 非常感谢!!这种努力是可观的。我没有想过将 Fraction 变成一个健壮的数据类。其他想法也很棒。但是,我不明白这部分:对于无效输入的情况,我使返回类型可以为空。如果输入无效,使用 addNumbers 的单击侦听器可以显示错误消息而不是 Fraction。将返回类型设为可空是什么意思?
  • ? 在一个类型之后意味着它允许有一个值nullkotlinlang.org/docs/reference/null-safety.html
猜你喜欢
  • 2019-11-21
  • 1970-01-01
  • 2017-11-19
  • 2012-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-04
  • 1970-01-01
相关资源
最近更新 更多