Я написал код в kotlin для оценки заданной строки из Divison для вычитания, он работает, но дает неправильный ответ, например, я получил строку x в первой строке с ответом -215,96666, тогда как ответ из кода -237,366666 idk где ошибка. я видел больше людей, использующих стек для этого, но я хотел сделать это для оценки строки
var x : String = "5+4-10x20-40/30x20+34/20"
fun div(x: String): String {
val lis1 = x.split("-").toMutableList()
for (ele1 in lis1) {
if ("/" in ele1) {
val pos1 = lis1.indexOf(ele1)
val lis2 = ele1.split("+").toMutableList()
for (ele2 in lis2) {
if ("/" in ele2) {
val pos3 = lis2.indexOf(ele2)
val lis3 = ele2.split("x").toMutableList()
for (ele3 in lis3) {
if ("/" in ele3) {
val pos4 = lis3.indexOf(ele3)
val lis4 = ele3.split("/")
val div = (lis4[0].toDouble() / lis4[1].toDouble()).toString()
lis3[pos4] = div
}
}
lis2[pos3] = lis3.joinToString("x")
}
}
lis1[pos1] = lis2.joinToString("+")
}
}
return (lis1.joinToString("-"))
}
fun mul(x : String) : String{
val lis1 = x.split("-").toMutableList()
for (ele1 in lis1) {
if ("x" in ele1){
val pos1 = lis1.indexOf(ele1)
val lis2 = ele1.split("+").toMutableList()
for(ele2 in lis2){
if ("x" in ele2){
val pos2 = lis2.indexOf(ele2)
val lis3 = ele2.split("x")
val mul = (lis3[0].toDouble() * lis3[1].toDouble()).toString()
lis2[pos2] = mul
}
}
lis1[pos1] = lis2.joinToString("+")
}
}
return (lis1.joinToString("-"))
}
fun add(x : String): String {
val lis1 = x.split("-").toMutableList()
for(ele1 in lis1){
if ("+" in ele1){
val pos1 = lis1.indexOf(ele1)
val lis2 = ele1.split("+")
val add = (lis2[0].toDouble() + lis2[1].toDouble()).toString()
lis1[pos1] = add
}
}
return (lis1.joinToString("-"))
}
fun sub(x : String) : String{
val lis1 = x.split("-").toMutableList()
var sub = 0.0
for(ele1 in lis1){
sub -= ele1.toDouble()
}
return (sub.toString())
}
fun eval(x: String): String {
val divanswer = div(x)
val mulanswer = mul(divanswer)
val addanswer = add(mulanswer)
return sub(addanswer)
}
fun main(args: Array<String>){
println(eval(x))
}
i wanted the answer as -215.96666 but the answer given by code is -237.366666
@ lukas.j Полный синтаксический анализатор - правильный путь, но я очень ценю креативность ОП. Они сами ищут способ, как это сделать, с таким настроем узнают гораздо больше, чем авторы типичных вопросов: "Как написать калькулятор, помогите". Кроме того, я думаю, что этот подход в конечном итоге должен работать, однако было бы довольно сложно добавить поддержку скобок.
@broot Я согласен с вами по поводу творчества и процесса обучения. Но, с другой стороны, вычисление арифметических выражений было решено несколько десятилетий назад, и, возможно, это не то место, куда нужно вкладывать время. Вероятно, два наиболее важных решения — это, во-первых, то, что я бы назвал «рекурсией выражения-терма-фактора», и, во-вторых, преобразование входной строки в стек операторов и операндов, а затем инфикс в постфикс и оценка стека. больше смысла тратить время на разработку пользовательского кода на основе этих известных решений.Но я понимаю, что вы имеете в виду в отношении этого вопроса.
@ lukas.j да, это похоже на неправильное место для вложения времени, но мне действительно нравится программировать, когда я решаю такие задачи, так что для меня это не похоже на трату времени, а просто заставляет меня заниматься тем, что мне нравится, я спросил мои друзья и на многих веб-сайтах, ответ был просто использовать стек или массив, чтобы сделать это, но если есть другой способ сделать это, но это беспорядок, я обязательно попробую...
В случае этого конкретного ввода есть две ошибки.
Первая ошибка связана с тем, что вы сначала обрабатываете +
, а затем -
, но в математике мы должны обрабатывать их вместе, слева направо. В результате ваш алгоритм обрабатывает это: 1-1+1
(правильный ответ: 1
) как: 1-(1+1)
(ответ: -1
). В качестве альтернативы, я считаю, что обработка -
сначала, а затем +
должна работать правильно.
Вторая ошибка заключается в том, что в sub()
вы начинаете с 0
и вычитаете даже первое число, но на самом деле первое число должно быть добавлено или использовано в качестве начального значения.
Я считаю, что после исправления этих двух ошибок он должен дать правильный ответ для этого конкретного ввода, но, вероятно, таких ошибок больше. Например, вы неправильно обрабатываете цепочки одного и того же оператора, вас интересует только первая пара, поэтому 1+1+1
становится 2
(а затем превращается в -2
из-за ранее упомянутой ошибки).
Общий совет: научитесь пользоваться отладчиком и анализируйте, как меняются ваши данные, пока код их обрабатывает. Даже если вы просто распечатаете свои промежуточные результаты: divanswer
, mulanswer
и addanswer
, а затем пропустите их через Google для обработки, вы заметите, что где-то на шаге add()
есть проблема. Затем промойте и повторяйте, пока все не будет работать правильно.
спасибо, это была часть вычитания и сложения, которая вызвала проблемы, теперь я изменил и объединил ее в одну, теперь я получаю правильный ответ для строк, которые я использовал, теперь мне нужно заполнить только скобки, еще раз спасибо за это. !
Спасибо @broot за то, что заметил это, проблема заключалась в части сложения и вычитания, теперь, когда я объединил их в один и получил правильные ответы для строк, которые я ввел, вот исправленный полный код.
var x : String = "5+4-10x20-40/30x20+34/20"
fun div(x: String): String {
val lis1 = x.split("-").toMutableList()
for (ele1 in lis1) {
if ("/" in ele1) {
val pos1 = lis1.indexOf(ele1)
val lis2 = ele1.split("+").toMutableList()
for (ele2 in lis2) {
if ("/" in ele2) {
val pos3 = lis2.indexOf(ele2)
val lis3 = ele2.split("x").toMutableList()
for (ele3 in lis3) {
if ("/" in ele3) {
val pos4 = lis3.indexOf(ele3)
val lis4 = ele3.split("/")
val div = (lis4[0].toDouble() / lis4[1].toDouble()).toString()
lis3[pos4] = div
}
}
lis2[pos3] = lis3.joinToString("x")
}
}
lis1[pos1] = lis2.joinToString("+")
}
}
return (lis1.joinToString("-"))
}
fun mul(x : String) : String{
val lis1 = x.split("-").toMutableList()
for (ele1 in lis1) {
if ("x" in ele1){
val pos1 = lis1.indexOf(ele1)
val lis2 = ele1.split("+").toMutableList()
for(ele2 in lis2){
if ("x" in ele2){
val pos2 = lis2.indexOf(ele2)
val lis3 = ele2.split("x")
val mul = (lis3[0].toDouble() * lis3[1].toDouble()).toString()
lis2[pos2] = mul
}
}
lis1[pos1] = lis2.joinToString("+")
}
}
return (lis1.joinToString("-"))
}
fun final(x: String): Double {
val substr = StringBuffer()
var answer = 0.0
var opr = '+'
for(ele in x.indices){
var current = x[ele]
if (current in '0'..'9' || current == '.'){
substr.append(current)
}
if (current == '-' || current == '+'){
var operand = substr.toString().toDouble()
substr.setLength(0)
when (opr){
'+' -> answer += operand
'-' -> answer -= operand
}
opr = current
}
}
val num = substr.toString().toDouble()
when(opr){
'+' -> answer += num
'-' -> answer -= num
}
return answer
}
fun eval(x: String): Double {
val divanswer = div(x)
return final(mul(divanswer))
}
fun main(args: Array<String>){
println(eval(x))
}
Я не думаю, что это должно быть сделано таким образом. Вам следует подумать о написании синтаксического анализатора для вычисления арифметических выражений.