基本计算器


20

您必须编写一个程序来评估将输入到计算器中的字符串。

程序必须接受输入并输出正确答案。对于不具有标准输入/输出功能的语言,您可以使用readLineprint

要求

  • 不使用任何“评估”功能
  • 可以处理浮点数和负数
  • 至少支持+,-,*和/运算符
  • 可以处理在运算符和数字之间包含一个或多个空格的输入
  • 从左到右评估表达式

最短的程序将获胜。如果出现平局,则首先提交的程序将获胜。

您可以假定输入有效并且遵循正确的格式

测试用例

输入项

-4 + 5

输出量

1


输入项

-7.5 / 2.5

输出量

-3


输入项

-2 + 6 / 2 * 8 - 1 / 2.5 - 18

输出量

-12

我的计算器使用后缀。另请参阅评估堆栈溢出的数学表达式以获取竞争(尽管我尚未检查规则是否相同)。
dmckee 2011年

3
第三个测试用例是错误的-无论您遵循标准操作顺序还是执行从左到右的所有操作。看第二个测试用例,您的计算器是否舍入每个运算的结果?
PleaseStand 2011年

修复了第二个和第三个测试用例,结果未四舍五入。
凯文·布朗

第三个测试用例不遵循标准的操作顺序。我们的答案应该吗?
约翰

1
使用命令行参数ARGV怎么办?因为shell会自动拆分并列出参数。
Ming-Tang

Answers:


7

Ruby- 74 69 67 65个字符

a=0
("+ "+$<.read).split.each_slice 2{|b,c|a=a.send b,c.to_f}
p a

1
而不是使用的b[0],b[1].to_f可以替换|b|使用|b,c|和使用b,c.to_f
Nemo157

\ o /谢谢!:-)
Arnaud Le Blanc

1
代替a.send(b,c.to_f)使用a.send b,c.to_f。它保存了一个字符
匿名胆小鬼

1
您可以使用$<代替ARGF
Dogbert

9

Befunge- 37 x 5 = 185 38 x 3 = 114个字符

由于Befunge不支持浮点,因此只能使用整数。

&v      /& _ #`&# "-"$# -#<          v
 >~:0`!#v_:" "`! #v_:","`#^_"*"`#v_&*>
 ^      ># $ .# @#<              >&+ 

说明

Befunge最大的区别在于,它不是像大多数语言一样线性的指令集;它是单字符指令的二维网格,控制可以在任何方向流动。

第一个&仅输入第一个数字。该v>然后重定向到控制在第二行的主路径。

~:0`!#v_

这将输入一个字符(~),将其复制(:),将零压入堆栈(0),弹出顶部的两个元素,并确定第二个元素是否大于第一个元素(` 我很惊讶您无法使用```来获取代码反引号(。),反转顶部元素(!)的真实性,如果为零则向右,否则向下(#v_)。

基本上,它检查输入是否-1不再代表输入。

># $ .# @

如果输入为-1原值,则丢弃重复的输入值($),将堆栈的顶部作为整数(.)输出,并暂停程序(@)。

:" "`! #v_

否则,重复类似的过程以确定输入是否小于或等于空格。如果是空格,则控制权下降,否则控制权向右移动。

^      ># $ .# @#<

如果是空格,则将其向左重定向(<); 使用跳过程序暂停(@),输出(.)和右重定向(>#。但是将执行丢弃操作以从堆栈中删除空间。最后,将其重定向到下一个执行(^)。

:","`#^_

如果它是不一样的过程来划分,如果它是在一个空间[+, *][-, \]在朝好的方向发展和同比分别。

 >~                         "*"`#v_&*>
 ^                               >&+

因为[+, *]它再次被拆分以确定它是a +还是a *。如果+向下,则输入下一个数字&+),然后将它们加在一起(),然后该控件回绕并重定向到下一个字符的主路径。如果是,*则输入(&)并乘以(*),然后直接回绕。

/& _ #`&# "-"$# -#<

因为[-, \]它从右边的标题开始。所述#的跳过字符之后他们因此初始路径是"-"`_它简单地确定是否是-/。如果是,/则继续输入(&)并除以(/)。如果是,-则它向右移动,再次跳过字符,以使其执行,&"-"$-结果是输入数字(&)将该-字符压入堆栈,然后丢弃("-"$),然后计算减法(-)。然后将控件重定向回主路径。


6

Python 3,105个字节

管理四个基本操作,但每个添加^或只需花费5个字符%

f=float
x,*l=input().split()
while l:o,y,*l=l;x,y=f(x),f(y);x=[x+y,x-y,x*y,x/y]['+-*/'.find(o)]
print(x)

操作优先级从左到右。


5

巨蟒(156)

from operator import*
while 1:
 l=raw_input().split();f=float
 while len(l)>2:l[:3]=({'*':mul,'/':div,'+':add,'-':sub}[l[1]](f(l[0]),f(l[2])),)
 print l[0]

1
使用Python 3可能更容易
jamylak 2013年

5

C- 168126个字符

main(c){float a,b;scanf("%f",&a);while(scanf("%s%f",&c,&b)!=-1)c=='+'?a+=b:c=='-'?(a-=b):c=='*'?(a*=b):(a/=b);printf("%f",a);}

5

TCL 8.6,57 48个字符。

  • 输入自变量:

    lm o\ b [las $argv a] {set a [exp $a$o$b]};pu $a
    
  • 从斯坦丁(64 53

    lm o\ b [las [ge stdin] a] {set a [exp $a$o$b]};pu $a
    

两种解决方案都必须使用交互式外壳。

我对待输入作为列表(Tcl的使用空格作为分隔符)采取的第一个元素,并将它指定a,那么我走过去的其余部分,以每次2层的元件,操作者和第二数量,应用操作上$a$b并分配结果到a。最后的结果是a


Ideone至少支持stdin。
Johannes Kuhn

最后,我击败了Ruby。不幸的是IDONE不支持Tcl的8.6,但我并不需要的结果的lmap那么foreach是一个很好的替代品。
Johannes Kuhn

4

Haskell:124114个字符

j[o]=o
j(u:m:b:o)=j$show((case m of{"+"->(+);"-"->(-);"*"->(*);"/"->(/)})(read u)(read b)):o
main=interact$j.words

一个很简单的答案,使用模式匹配和简单的case语句进行繁重的工作。用法:

> ./calc <<< "123 - 12 + -12 / 12.124 * 9.99 - 1"
80.57456285054437

1
而不是((case m of{..})(read u)(read b))您可以写((case m of{..}$read u)$read b),少写两个字符。
swish 2014年

4

C:111108个字符

main(c){float a,b;for(scanf("%f ",&a);~scanf("%c%f ",&c,&b);a=c^43?c%5?c%2?a/b:a*b:a-b:a+b);printf("%f",a);}

它满足所有要求和用法:

> ./calc <<< "-43 - 56 + 14.123 / -13.22"
6.420348

1
~scanf可以代替+1。同样,c^45-> c%5c^42-> c%2应该可以工作。
ugoren

@MDXF不在我的机器上,它通过了这里的每个测试用例。我正在相当现代的Intel Macbook上使用Clang进行编译,并且运行得非常好(我刚刚再次对其进行了测试,我从此处复制粘贴了代码,并且没有任何标志地对其进行了编译)。您正在使用什么编译器,处理器体系结构和OS?
Fors

@Fors我相信我有一些奇怪的标志在引起奇怪的行为。我的错误,现在对我有用。抱歉打扰你。
MD XF

3

的C ++ 0x 205 203 198 194个字符

#include<iostream>
#define P [](F l,F r){return l
int main(){typedef float F;F r,v,(*a[])(F,F)={P*r;},P+r;},0,P-r;},0,P/r;}};std::cin>>r;for(char o;std::cin>>o>>v;)r=a[o-42](r,v);std::cout<<r;}

格式正确:

#include<iostream>

int main()
{
    float r,v;
    float (*a[])(float,float)   ={  [](float l,float r){return l*r;},
                                    [](float l,float r){return l+r;},
                                    0,
                                    [](float l,float r){return l-r;},
                                    0,
                                    [](float l,float r){return l/r;}
                                 };

    std::cin>>r;
    for(char o;std::cin>>o>>v;)
        r=a[o-42](r,v);

    std::cout<<r;
}

3

佩尔(97)

$b=shift;eval"\$b$r=$s"while($r=shift,$s=shift);print$b

从参数中读取

$b=shift;$b=($r eq'+'?$b+$s:$r eq'-'?$b-$s:$r eq'*'?$b*$s:$b/$s)while($r=shift,$s=shift);print$b;

从输入中读取

@_=split/ /,<>;$b=shift@_;$b=($r eq'+'?$b+$s:$r eq'-'?$b-$s:$r eq'*'?$b*$s:$b/$s)while($r=shift@_,$s=shift@_);print$b

3

PostScript(145)

另一个PostScript条目(感谢luser droog挖掘了PostScript感兴趣的高尔夫!):

[/+{add}/-{sub}/*{mul}/{div}>>begin(%stdin)(r)file
999 string readline
pop{token not{exit}if
count 4 eq{3 1 roll
4 1 roll
cvx exec}if
exch}loop
=

未打高尔夫球:

[/+{add}/-{sub}/*{mul}/ {div}>>begin
% Read the input
(%stdin)(r)file 999 string readline pop
{                        % .. string
  token not{exit}if      % .. string token
  % If we have 4 objects on the stack, we have two operands, one operator
  % and the input string. This means, we can calculate now.
  count 4 eq{            % a op string b
    % perform operation a op b = c (where op can be +,-,*,/)
    3 1 roll             % a b op string
    4 1 roll             % string a b op 
    cvx exec             % string c
  }if                    % string token (or c)
  exch                   % token string
}loop
=

你一直在打我!+1这非常令人兴奋。
luser droog 2012年

如果您能击败我的填字游戏,我会给您赏金!注意:您只能在帖子成为CW之前进行10次编辑,而投票不能为您赢得代表积分。
luser droog 2012年

我一直在打败你,因为我只选择了打败你的那些人;-)。我不确定是否可以使用填字游戏网格。我可能会尝试,但仅在几周后。
Thomas W.

1
社区维基。这意味着帖子已被编辑了很多次,现在属于社区。任何用户都可以编辑它(绕过通常建议的编辑所需的主持人批准),并且没有更多分数。因此,无论您做什么,都请停在第9版。我几乎在吉他选项卡上将其吹灭了。
luser droog 2012年

1
忽略所有CW困扰。他们解决了!
luser droog 2012年

3

的Python-308

import sys;i=sys.argv[1].split();o=[];s=[];a=o.append;b=s.pop;c=s.append
for t in i:
 if t in"+-*/":
  if s!=[]:a(b())
  c(t)
 else:a(t)
if s!=[]:a(b())
for t in o:
 if t=="+":c(b()+b())
 elif t=="-":m=b();c(b()-m)
 elif t=="*":c(b()*b())
 elif t=="/":m=b();c(b()/m)
 else:c(float(t))
print(b())

可读版本:

# Infix expression calc

import sys

# Shunting-yard algorithm
input = sys.argv[1].split()
output = []
stack = []

for tkn in input:
    if tkn in "+-*/":
        while stack != []:
            output.append(stack.pop())
        stack.append(tkn)
    else:
        output.append(tkn)

while stack != []:
    output.append(stack.pop())

# Eval postfix notation
for tkn in output:
    if tkn == "+":
        stack.append(stack.pop() + stack.pop())
    elif tkn == "-":
        tmp = stack.pop()
        stack.append(stack.pop() - tmp)
    elif tkn == "*":
        stack.append(stack.pop() * stack.pop())
    elif tkn == "/":
        tmp = stack.pop()
        stack.append(stack.pop()/tmp)
    else:
        stack.append(float(tkn))

print(stack.pop())

将表达式作为命令行参数,在标准输出上输出。


2

附言(340)

/D<</+{add}/-{sub}/*{mul}/ {div}>>def/eval{/P null def{token not{exit}if exch/rem exch def
dup D exch known{/P load null ne{D/P load get exch/P exch def exec}{/P exch def}ifelse}if
rem}loop/P load null ne{D/P load get exec}if}def {(> )print flush{(%lineedit)(r)file
dup bytesavailable string readline pop eval == flush}stopped{quit}if}loop

还有一点可读性:

%!
/oper<</+{add}/-{sub}/*{mul}/ {div}>>def

/eval{
    /op null def
    {
        token not {exit} if
        exch /rem exch def
        dup oper exch known {
            /op load null ne {
                oper /op load get
                exch /op exch def
                exec
            }{
                /op exch def
            } ifelse
        } if
        rem
    } loop
    /op load null ne { oper /op load get exec } if
} def

{
    (> )print flush
    {
    (%lineedit)(r)file
    dup bytesavailable string readline pop
    eval == flush
    } stopped { quit } if
} loop

2

JavaScript(压缩208个字符)

为了清楚起见,这是我压缩之前的代码(JS-Fiddle):

function math(match, leftDigit, operator, rightDigit, offset, string) {
    var L = parseFloat(leftDigit)
    var R = parseFloat(rightDigit)
    switch (operator)
    {
        case '*': return L*R;
        case '/': return L/R;
        case '+': return L+R;
        case '-': return L-R;
    }
};

str = prompt("Enter some math:", "-2 + 6 / 2 * 8 - 1 / 2.5 - 18").replace(/ /g, "");
var mathRegex = /(\-?\d+\.?\d*)([\*\/\+\-])(\-?\d+\.?\d*)/;
while(mathRegex.test(str)) {
    str = str.replace(mathRegex, math);
}
alert(str)

在这里,它压缩为208个字符(JS-Fiddle):

function m(x,l,o,r){
    L=(f=parseFloat)(l);
    R=f(r);
    return o=='*'?L*R:o=='/'?L/R:o=='+'?L+R:L-R;
};

M=/(\-?\d+\.?\d*)([\*\/\+\-])(\-?\d+\.?\d*)/;
for(s=prompt().replace(/ /g, "");M.test(s);s=s.replace(M,m)){};
alert(s)

由于我以分号结束行,因此所有可移动的空格都被忽略以进行字符计数,但为了清楚起见而保留了该空格。


2

哈斯克尔-124

let p=let f[x]=Just$read x;f(x:o:r)=lookup o[("-",(-)),("+",(+)),("*",(*)),("/",(/))]<*>f r<*>Just(read x)in f.reverse.words

结果将包装在Maybemonad中

λ: p"-2 + 6 / 2 * 8 - 1 / 2.5 - 18"
Just (-12.0)

另外,它还要求<*>从中导入Control.Applicative,但是导入可以在代码外部完成,因此希望它允许。


2

C# (234) (231) (229) (223) (214)

class A{void Main(string[]s){var n=1;var o="";var r=0F;foreach(var t in s){if(n>0){var v=float.Parse(t);if(o=="")r=v;if(o=="+")r+=v;if(o=="-")r-=v;if(o=="*")r*=v;if(o=="/")r/=v;}o=t;n=-n;}System.Console.Write(r);}}

class A{
    void Main(string[] s)
    {
      var n = 1;
      var o = "";
      var r = 0F;

      foreach (var t in s)
      {
        if (n > 0)
        {
          var v = float.Parse(t);
          if (o == "") r = v;
          if (o == "+") r += v;
          if (o == "-") r -= v;
          if (o == "*") r *= v;
          if (o == "/") r /= v;
        }
        o = t;
        n = -n;
      }
      System.Console.Write(r);
    }
}

我得到的是“ 1 + 1”的“ 0”。 IDEONE
Rob

@Mike输入作为参数,而不是stdin。
Johannes Kuhn 2013年

1

JavaScript(87个字符)

alert(prompt().split(/ +/).reduce((a,b,i)=>i%2?(o=b,a):o+1-0?a-b*-(o+1):o<'/'?a*b:a/b))

1

Java 11,151(作为lambda函数)

s->{float r=0,t;int o=43,q;for(var x:s.split(" ")){if(x.length()>1|(q=x.charAt(0))>47){t=new Float(x);r=o<43?r*t:o<44?r+t:o<46?r-t:r/t;}o=q;}return r;}

Lambda函数接受String输入并输出浮点数。

在线尝试。

Java 11,241个字节(作为具有要求的I / O的完整程序)

interface M{static void main(String[]a){float r=0,t;int o=43,q;for(var x:new java.util.Scanner(System.in).nextLine().split(" ")){if(x.length()>1|(q=x.charAt(0))>47){t=new Float(x);r=o<43?r*t:o<44?r+t:o<46?r-t:r/t;}o=q;}System.out.print(r);}}

完整程序通过STDIN接受字符串行并输出到STDOUT。

在线尝试。

说明:

interface M{                  // Class
  static void main(String[]a){//  Mandatory main-method
    float r=0,                //   Result float, starting at 0
          t;                  //   Temp float
    int o=43,                 //   Operator flag, starting at '+'
        q;                    //   Temp operator flag
    for(var x:new java.util.Scanner(System.in)
                              //   Create an STDIN-reader
               .nextLine()    //   Get the user input
               .split(" ")){  //   Split it on spaces, and loop over it:
      if(x.length()>1         //    If the current String length is larger than 1
                              //    (work-around for negative values)
         |(q=x.charAt(0))>47){//    Or the first character is an operator
                              //    (and set `q` to this first character at the same time)
        t=new Float(x);       //     Convert the String to a float, and set it to `t`
        r=                    //     Change `r` to:
          o<43?               //      If `o` is a '*':
            r*t               //       Multiply `r` by `t`
          :o<44?              //      Else-if `o` is a '+':
            r+t               //       Add `r` and `t` together
          :o<46?              //      Else-if `o` is a '-':
            r-t               //       Subtract `t` from `r`
          :                   //      Else (`o` is a '/'):
            r/t;}             //       Divide `r` by `t`
      o=q;}                   //    And at the end of every iteration: set `o` to `q`
    System.out.print(r);}}    //    Print the result `r` to STDOUT

1

05AB1E,30 个字节

#ćs2ôívy`…+-*sk©i-ë®>i+ë®<i*ë/

在线尝试验证所有测试用例

说明:

#           # Split the (implicit) input-string by spaces
 ć          # Pop the list, and push the remainder and first item separated to the stack
  s         # Swap so the remainder is at the top of the stack
   2ô       # Split it into parts of size 2 (operator + number pairs)
     í      # Reverse each pair so the numbers are before the operators
v           # Loop over each of the pairs:
 y`         #  Push the number and operator separated to the stack
   …+-*     #  Push a string "+-*"
       sk   #  Get the index of the operator in this string
         ©  #  Store this index in the register (without popping)
   i        #  If the index is 1 (the "-"):
    -       #   Subtract the numbers from each other
   ë®>i     #  Else-if the index is 0 (the "+"):
       +    #   Add the numbers together
   ë®<i     #  Else-if the index is 2 (the "*"):
       *    #   Multiply the numbers with each other
   ë        #  Else (the index is -1, so "/"):
    /       #   Divide the numbers from each other
            # (and output the result implicitly)

如果eval允许使用内置函数,则可以使用另一种方法(16个字节):

#ćs2ôJv…(ÿ)y«}.E

在线尝试验证所有测试用例

说明:

#ćs2ô    # Same as above
     J   # Join each operator+number pair together to a single string
v        # Loop over the operator+number strings:
 …(ÿ)    #  Surround the top of the stack in parenthesis
     y«  #  And append the operator+number string
}.E      # After the loop: evaluate the string using a Python-eval

这将在使用内置函数之前更改"-2 + 6 / 2 * 8 - 1 / 2.5 - 18"为(直接使用将使运算符具有over 优先级,因此首先使用括号进行转换)。"((((((-2)+6)/2)*8)-1)/2.5)-18"eval.E*/+-

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.