不同语言中的除法
前言
今天看到一道题目:逆波兰表达式求值,如下:
根据 逆波兰表示法,求表达式的值。
有效的算符包括 +、-、*、/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
说明:
整数除法只保留整数部分。
给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
示例 1:
输入:tokens = ["2","1","+","3","*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
示例 2:输入:tokens = ["4","13","5","/","+"]
输出:6
解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
示例 3:输入:tokens = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"]
输出:22
解释:
该算式转化为常见的中缀算术表达式为:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22
解答
其实这道题本事并不难,用栈即可。
逆波兰表达式严格遵循「从左到右」的运算。计算逆波兰表达式的值时,使用一个栈存储操作数,从左到右遍历逆波兰表达式,进行如下操作:
如果遇到操作数,则将操作数入栈;
如果遇到运算符,则将两个操作数出栈,其中先出栈的是右操作数,后出栈的是左操作数,使用运算符对两个操作数进行运算,将运算得到的新操作数入栈。
整个逆波兰表达式遍历完毕之后,栈内只有一个元素,该元素即为逆波兰表达式的值。
面对这种简单题,我重拳出击,写下了如下代码:
1 class Solution(object): 2 def evalRPN(self, tokens): 3 """ 4 :type tokens: List[str] 5 :rtype: int 6 """ 7 data_stack = [] 8 for i in tokens: 9 if i not in ['+', '-', '*', '/']: 10 data_stack.append(int(i)) 11 else: 12 b = data_stack.pop() 13 a = data_stack.pop() 14 if i == '+': 15 res = a + b 16 elif i == '-': 17 res = a - b 18 elif i == '*': 19 res = a * b 20 else: 21 res = a // b 22 data_stack.append(res) 23 return data_stack[-1]
测了前两个用例,通过,完美,提交,哦豁,错了,错误用例正好就是第三个测试用例。
我以为有哪里不对,于是我打印了每一步的计算过程,终于发现了问题
在计算 6 / -132 的时候,题解中给的解答是:
6 / -132 = 0
但是,我的解答是
6 // -132 = -1 (python 的"/" 是真正的除法, 一般用『/』取整)
因此,也就引入了今天的问题。
python3
- 真除法: /
- 地板除 实质是向下取整 //
- int() 直接截断 小数取整会采用比较暴力的截断方式 正数和负数是不一样的,注意和//的区别
- math.ceil() 向上取整
math.floor() 向下取整
Java
1 public class TestDivide { 2 public static void main(String[] args) { 3 System.out.println("截取整数部分"); 4 System.out.println("1 / 3 = " + 1 / 3); 5 System.out.println("6 / 3 = " + 6 / 3); 6 System.out.println("6 / 4 = " + 6 / 4); 7 System.out.println("-3 / 2 = " + -3 / 2); 8 9 System.out.println("真实除法"); 10 System.out.println("1.0 / 3 = " + 1.0 / 3); 11 System.out.println("6.0 / 3 = " + 6.0 / 3); 12 System.out.println("6.0 / 4 = " + 6.0 / 4); 13 System.out.println("-3.0 / 2 = " + -3.0 / 2); 14 15 System.out.println("向上取整"); 16 System.out.println("Math.ceil(-1.1) = " + Math.ceil(-1.1)); 17 System.out.println("Math.ceil(-1.5) = " + Math.ceil(-1.5)); 18 System.out.println("Math.ceil(1.1) = " + Math.ceil(1.1)); 19 System.out.println("Math.ceil(1.5) = " + Math.ceil(1.5)); 20 21 System.out.println("向下取整"); 22 System.out.println("Math.floor(-1.1) = " + Math.floor(-1.1)); 23 System.out.println("Math.floor(-1.5) = " + Math.floor(-1.5)); 24 System.out.println("Math.floor(1.1) = " + Math.floor(1.1)); 25 System.out.println("Math.floor(1.5) = " + Math.floor(1.5)); 26 } 27 }
结果如下:
>>> 截取整数部分 1 / 3 = 0 6 / 3 = 2 6 / 4 = 1 -3 / 2 = -1 真实除法 1.0 / 3 = 0.3333333333333333 6.0 / 3 = 2.0 6.0 / 4 = 1.5 -3.0 / 2 = -1.5 向上取整 Math.ceil(-1.1) = -1.0 Math.ceil(-1.5) = -1.0 Math.ceil(1.1) = 2.0 Math.ceil(1.5) = 2.0 向下取整 Math.floor(-1.1) = -2.0 Math.floor(-1.5) = -2.0 Math.floor(1.1) = 1.0 Math.floor(1.5) = 1.0
Go
1 import ( 2 "fmt" 3 "math" 4 ) 5 6 func main() { 7 x := 1.1 8 fmt.Println(1 / 2) // 0 9 fmt.Println(1 / 3) // 0 10 fmt.Println(-1 / 3) // 0 11 fmt.Println(-4 / 5) // 0 12 13 fmt.Println(1.0 / 2) // 0.5 14 fmt.Println(1.0 / 3) // 0.33333333333 15 fmt.Println(-1.0 / 3) // -0.333333333333 16 fmt.Println(-4.0 / 5) // -0.8 17 18 fmt.Println(math.Ceil(x)) // 2 19 fmt.Println(math.Floor(x)) // 1 20 }