기본 계산기


20

계산기에 입력 할 문자열을 평가하는 프로그램을 작성해야합니다.

프로그램은 입력을 받아들이고 정답을 출력해야합니다. 표준 입 / 출력 기능이없는 언어의 경우 기능 readLine및을 가정 할 수 있습니다 print.

요구 사항

  • "eval"함수를 사용하지 않습니다
  • 부동 소수점 및 음수 처리 가능
  • 최소한 +,-, * 및 / 연산자를 지원합니다
  • 연산자와 숫자 사이에 하나 이상의 공백이 포함 된 입력을 처리 할 수 ​​있습니다.
  • 왼쪽에서 오른쪽으로 표현을 평가합니다

가장 짧은 프로그램이 이깁니다. 동점 일 경우, 먼저 제출 된 프로그램이 승리합니다.

입력이 유효하고 올바른 형식을 따른다고 가정 할 수 있습니다

테스트 사례

입력

-4 + 5

산출

1


입력

-7.5 / 2.5

산출

-3


입력

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

산출

-12

내 계산기postfix를 사용합니다 . 경쟁을 위해 스택 오버플로에서 수학 표현식 평가를 참조하십시오 (규칙이 동일한 지 확인하지는 않았지만).
dmckee

3
세 번째 테스트 사례는 표준 작업 순서를 따르거나 모든 작업을 왼쪽에서 오른쪽으로 수행하는지 여부입니다. 두 번째 테스트 사례를 살펴보면 계산기가 각 작업의 결과를 반올림합니까?
PleaseStand

두 번째 및 세 번째 테스트 사례를 수정했는데 결과가 반올림되지 않았습니다.
케빈 브라운

세 번째 테스트 사례는 표준 작업 순서를 따르지 않습니다. 우리의 대답은되어야합니까?
John

1
명령 행 인수 ARGV를 사용하는 것은 어떻습니까? 쉘이 자동 분할하고 인수를 나열하기 때문입니다.
Ming-Tang

답변:


7

루비 -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 의 가장 큰 특징은 대부분의 언어와 같이 선형적인 명령어 세트가 아니라는 점입니다. 제어는 모든 방향으로 흐를 수있는 단일 문자 명령어의 2 차원 격자입니다.

첫 번째는 &단순히 첫 번째 숫자를 입력합니다. v하고 >다음 두 번째 행의 주 경로로 리디렉션 제어.

~:0`!#v_

이것은 문자 ( ~)를 입력하고 그것을 복제 ( :)하고 스택에 0을 푸시 하고 ( ) 0상위 두 요소를 팝하고 두 번째 요소가 첫 번째 요소보다 큰지를 결정합니다 ( ` ````를 사용하여 얻을 수 없다는 것에 놀랐습니다. 코드 역 따옴표. ), 반전 상부 부재 (의 truthiness는 !그 아래, 그렇지 않으면 0 인 경우), 그 다음 바로 진행한다 ( #v_).

기본적으로 입력이 -1더 이상 입력을 나타내지 않는지 확인합니다 .

># $ .# @

입력이 -1복제 된 입력 값을 버린 경우 ( $) 스택의 맨 위가 정수 ( .) 로 출력되고 프로그램이 중지됩니다 ( @).

:" "`! #v_

그렇지 않으면 입력이 공백보다 작거나 같은지 판별하기 위해 유사한 프로세스가 반복됩니다. 공간이 있으면 제어 장치가 내려 가고 그렇지 않으면 제어 장치 헤드가 올바르게 작동합니다.

^      ># $ .# @#<

공백이면 왼쪽 ( <)으로 리디렉션됩니다 . 프로그램 정지 ( @), 출력 ( .) 및 오른쪽 방향 재 지정 ( >)은 모두 다음을 사용하여 건너 뜁니다 #. 그러나 폐기는 스택에서 공간을 제거하기 위해 실행됩니다. 마지막으로 다음 실행을 시작하도록 리디렉션됩니다 ( ^).

:","`#^_

공간이 아닌 경우 동일한 프로세스를 사용하여 각각 오른쪽 또는 위쪽 [+, *]또는 [-, \]위쪽 으로 분할되어 분할됩니다 .

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

왜냐하면 [+, *]그것이 a +인지 또는 a 인지를 결정하기 위해 다시 분할되기 때문입니다 *. 경우 +는 아래로 지시되어 그 다음 번호를 입력 (이다 &) 그들은 (추가 +컨트롤이 다음 주위에 감싸고 다음 문자에 대한 기본 경로까지 재 지정됩니다). 그렇다면 *입력 ( &)과 곱하기 ( *)를 직접 감 쌉니다.

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

들어 [-, \]는 바로 제목을 시작 떠났다. 는 #뒤에 나오는 문자를 건너 뛰므로 초기 경로는 "-"`_단순히 경로 인지 -또는 아닌지를 결정합니다 /. 그렇다면 /계속 입력 ( &) 및 나누기 ( /)로 남겨 둡니다 . 만약 그렇다면 -그것은 자신을 실행하므로 다시 문자를 건너 뛰고 바로 헤드 &"-"$-(숫자가 입력 결과 &)에 -문자가 다음 폐기 스택 (푸시되고 "-"$), 그리고 차분 산출되는 ( -). 그런 다음 컨트롤이 기본 경로로 다시 리디렉션됩니다.


6

파이썬 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
파이썬 3을 사용하는 것이 더 쉽다.
jamylak

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
    
  • Stdin에서 ( 64 53 )

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

두 솔루션 모두에 대화식 쉘을 사용해야합니다.

I리스트로서 입력 치료의 첫 번째 요소를 가지고 그것을 할당 (Tcl은 구분자로서 스페이스를 사용) a, 그때 나머지 걸어 2 개 요소마다, 작업자 및 제 번호 복용에 오퍼레이터를 적용 $a하고 $b상기 할당을 에 결과 a. 결국 결과는입니다 a.


Ideone 은 최소한 stdin을 지원합니다.
Johannes Kuhn

마침내 나는 루비를 이겼다. 불행하게도 Idone은은 은 Tcl 8.6 지원하지 않지만의 나는 결과를 필요가 없습니다 lmap그래서 foreach좋은 대신합니다.
Johannes Kuhn

4

하스켈 : 124114

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

패턴 일치와 무거운 리프팅에 대한 간단한 사례 설명을 사용하는 다소 간단한 대답입니다. 용법:

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

1
대신 2자를 적게 ((case m of{..})(read u)(read b))쓸 수 있습니다 ((case m of{..}$read u)$read b).

4

C : 111

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

포스트 스크립트 (145)

또 다른 PostScript 항목 (PostScript에 흥미로운 골프를 파는 것에 대한 luser droog 덕분에) :

[/+{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

당신이 내 낱말을 이길 수 있다면 , 나는 당신에게 현상금을 줄 것이다! NB 게시물이 CW가되기 전에 10 번만 편집 할 수 있으며 투표로 인해 rep 포인트가 적립되지 않습니다.
luser droog

내가 당신 이길 있는 것들만을 선택했기 때문에 나는 당신을 계속 때리고 ;-). 크로스 워드 그리드를 사용할 수 있는지 잘 모르겠습니다. 몇 주만에 시도해 볼 수 있습니다.
Thomas W.

1
커뮤니티 위키. 게시물이 커뮤니티에 속한 여러 번 편집되었음을 의미합니다. 모든 사용자는 일반적인 제안 편집에 필요한 중재자 승인을 무시 하고 더 이상 편집 할 수 없습니다. 그래서 당신이 무엇을하든 Rev 9에서 멈추십시오. 나는 기타 탭 1에서 거의 그것을 날려 버렸습니다.
luser droog

1
CW 그립을 모두 무시하십시오. 그들은 그것을 고쳤다!
luser droog

3

파이썬-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

자바 스크립트 (208 자 압축)

명확하게하기 위해이 코드는 압축 하기 전에 코드입니다 ( JS-Fiddle of ).

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 of ) :

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

결과는 Maybe모나드 로 포장됩니다

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

또한 <*>에서 가져 오기 가 필요 Control.Applicative하지만 코드 외부 에서 가져 오기 를 수행 할 수 있으므로 허용되기를 바랍니다.


2

씨# (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

1

자바 스크립트 (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 (람다 함수)

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

문자열 입력을 받아 float를 출력하는 Lambda 함수

온라인으로 사용해보십시오.

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을 통해 String-line을 취하여 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"하기 "((((((-2)+6)/2)*8)-1)/2.5)-18"전에로 바뀔 것입니다 eval( .E직접 사용 하면 연산자가 우선 순위를 */가지 +-므로 괄호로 먼저 변환됩니다).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.