表达式1 * 2 + 2 / 3-2 * 3 * 5 + 1/2/3的正确结果应该是 - 27.1666667,但我只能得到 - 27.1666666。为什么? [英] The correct result for the expression 1*2+2/3-2*3*5+1/2/3 should be - 27.1666667 but I only keep getting - 27.1666666. Why?

查看:123
本文介绍了表达式1 * 2 + 2 / 3-2 * 3 * 5 + 1/2/3的正确结果应该是 - 27.1666667,但我只能得到 - 27.1666666。为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的计算器应用程序代码,我正在使用递归。



Here is my code for a calculator application, I'm using recursion.

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;
            }

        }





我尝试过:



我试图使用Math.Round(res,6)将res小数点向上舍入到6,但它给出了相同的答案。我不知道还能做什么._。



What I have tried:

I've tried to round res decimals up only til 6 using Math.Round(res,6) but it gives the same answer. I don't know what else to do ._.

推荐答案

因为用浮点数做* any * math本质上是近似值。如果你想要更高的精度,请使用十进制类型(但要注意带小数类型的数学会花费更多时间)。
Because doing *any* math with floating point numbers is essentially an approximation. If you want more precision, use decimal types instead (but be aware that math with decimal types takes a little more time).


现在是时候阅读:每个计算机科学家应该了解浮点运算 [ ^ ]。
It is time to read: "What Every Computer Scientist Should Know About Floating-Point Arithmetic"[^].


执行浮点运算时,总会出现舍入错误。此外,大多数浮点值无法准确表示。



在你的情况下,你不仅要通过解析输入字符串和执行数学运算来得到舍入错误,而且 - 更重要的是 - 还要将每个中间结果作为字符串返回将其转换回浮点值以进行进一步计算。因此,转换舍入误差会累积。



为避免这种情况,您应该从 execute()功能。然后错误将变得更小,当你用10位有效数字打印它时你应该得到预期的结果。
You will always get rounding errors when performing floating point operations. Also most floating point values can't be represented exactly.

In your case you are not only getting rounding errors from parsing the input string and performing the mathematical operations but - more important - also by returning each intermediate result as string and converting that back to a floating point value for further calculation. As a result the conversion rounding errors accumulate.

To avoid this you should return floating point values from your execute() function. Then the errors will become much smaller and you should get the expected result when printing it with 10 significant digits.


这篇关于表达式1 * 2 + 2 / 3-2 * 3 * 5 + 1/2/3的正确结果应该是 - 27.1666667,但我只能得到 - 27.1666666。为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆