mariaclara Ответов: 3

Правильный результат для выражения 1*2+2/3-2*3*5+1/2/3 должно быть - 27.1666667, но я только продолжаю получать - 27.1666666. Почему?


Вот мой код для приложения калькулятора, я использую рекурсию.

public String execute(String screen_text)
        {
            String[] operand = {};
            String res = screen_text;
            double tmp=0;

            if (screen_text.Contains('+'))
            {
                operand = screen_text.Split('+');
                for (int a = 0; a < operand.Length; a++)
                    tmp += double.Parse(execute(operand[a]));
                
                res = Convert.ToString(tmp);
                return res;
            }
            else if (screen_text.Contains('-'))
            {
                operand = screen_text.Split('-');
                tmp = double.Parse(execute(operand[0]));
                for (int b = 1; b < operand.Length; b++)
                    tmp -= double.Parse(execute(operand[b]));
                
                res = Convert.ToString(tmp);
                return res;
            }
            else if (screen_text.Contains('x'))
            {
                operand = screen_text.Split('x');
                tmp = double.Parse(execute(operand[0]));
                for (int c = 1; c < operand.Length; c++)
                    tmp *= double.Parse(execute(operand[c]));
                
                res = Convert.ToString(tmp);
                return res;
            }
            else if (screen_text.Contains('/'))
            {
                operand = screen_text.Split('/');
                tmp = double.Parse(execute(operand[0]));
                for (int d = 1; d < operand.Length; d++)
                    tmp /= double.Parse(execute(operand[d]));
               
                res = Convert.ToString(tmp);
                return res;
            }
            else
            {
                return res;
            }

        }


Что я уже пробовал:

Я пытался округлить десятичные дроби только до 6, используя математику.Раунд (res, 6), но он дает тот же ответ. Я не знаю, что еще делать.

mariaclara

Я имел в виду округление десятичных знаков res только до 7, следовательно, математика.Раунд (res, 7).
Я не вижу никакой опции "редактировать вопрос" на этой странице с помощью моего телефона, это странно

Richard MacCutchan

Улучшить вопрос ссылка выше.

3 Ответов

Рейтинг:
7

Jochen Arndt

Вы всегда будете получать ошибки округления при выполнении операций с плавающей запятой. Кроме того, большинство значений с плавающей запятой не могут быть представлены точно.

В вашем случае вы не только получаете ошибки округления при разборе входной строки и выполнении математических операций, но - что более важно - также возвращаете каждый промежуточный результат в виде строки и преобразуете его обратно в значение с плавающей запятой для дальнейшего вычисления. В результате накапливаются ошибки округления преобразования.

Чтобы избежать этого, вы должны возвращать значения с плавающей запятой из вашего execute() функция. Тогда ошибок станет намного меньше, и вы должны получить ожидаемый результат при печати его с 10 значащими цифрами.


mariaclara

Спасибо вам за эту идею! Я попытался сделать параметр плавающим, но это разрушило мой метод рекурсии: & lt; однако я придумал лучший способ для арифметических операций работать с точными результатами без использования рекурсии и все еще используя поплавки. Еще раз спасибо!

Jochen Arndt

Спасибо вам за ваши отзывы и принятие решения.

Он будет работать рекурсивно при возврате tmp вместо res и setting
tmp = двойной.Синтаксический анализ(screen_text);
когда нет никакой операции (условие else).

mariaclara

Да? Я должен попробовать. Спасибо!

Рейтинг:
0

#realJSOP

Потому что делать* любую * математику с числами с плавающей запятой-это, по сути, аппроксимация. Если вам нужна большая точность, используйте вместо этого десятичные типы (но имейте в виду, что математика с десятичными типами занимает немного больше времени).