IT story

수학 파서의 스마트 디자인?

hot-time 2021. 1. 6. 20:24
반응형

수학 파서의 스마트 디자인?


수학 파서를 디자인하는 가장 현명한 방법은 무엇입니까? 내 말은 수학 문자열 (예 : "2 + 3/2 + (2 * 5)")을 받아서 계산 된 값을 반환하는 함수입니다. 나는 오래 전에 VB6에서 하나를 작성했지만 결국 부풀어 오르고 휴대 성이 좋지 않습니다 (또는 그 문제에 대해 똑똑합니다 ...). 일반적인 아이디어, 의사 코드 또는 실제 코드가 높이 평가됩니다.


꽤 좋은 접근법은 두 단계를 포함합니다. 첫 번째 단계는 식을 infix에서 postfix로 변환하는 것입니다 (예 : Dijkstra의 shunting yard 사용 ). 완료되면 후위 평가자 를 작성하는 것은 매우 간단합니다 .


수학 파서 설계에 대한 몇 가지 블로그 게시물을 작성했습니다. 일반적인 소개 , 문법대한 기본 지식 , Ruby로 작성된 샘플 구현테스트 스위트가 있습니다. 아마도 이러한 자료가 유용 할 것입니다.


몇 가지 접근 방식이 있습니다. 많은 코드를 작성할 필요없이 답을 얻기 위해 동적 코드를 생성하고 실행할 수 있습니다. .NET에서 런타임 생성 코드를 검색하기 만하면 주변에 많은 예제가 있습니다.

또는 실제 파서를 만들고 식을 평가하는 데 사용되는 작은 구문 분석 트리를 생성 할 수 있습니다. 다시 말하지만 이것은 기본 표현에 대해 매우 간단합니다. 내가 거기에 수학 파서를 가지고 있다고 생각하는 codeplex를 확인하십시오. 또는 예제를 포함 할 BNF를 찾으십시오. 컴파일러 개념을 소개하는 모든 웹 사이트에는이를 기본 예제로 포함합니다.

Codeplex 표현식 평가 기


나는 이것이 오래되었다는 것을 알고 있지만 더 큰 앱의 일부로 계산기를 개발하려고 시도하고 수용 된 답변을 사용하여 몇 가지 문제를 겪었습니다. 링크는이 문제를 이해하고 해결하는 데 대단히 도움이되었으며 할인되어서는 안됩니다. 저는 Java로 Android 앱을 작성하고 "문자열"이라는 표현의 각 항목에 대해 사용자가 키패드에 입력 할 때 실제로 ArrayList에 문자열을 저장했습니다. 중위에서 후 위로 변환하기 위해 ArrayList의 각 문자열을 반복 한 다음 새로 배열 된 후위 Strings ArrayList를 평가했습니다. 이것은 소수의 피연산자 / 연산자에게는 환상적 이었지만 특히식이 정수가 아닌 것으로 평가되기 시작하면서 더 긴 계산이 일관되게 꺼져있었습니다. Infix에서 Postfix 로의 변환을 위해 제공된 링크에서, 스캔 된 항목이 연산자이고 topStack 항목이 더 높은 우선 순위를 갖는 경우 스택을 팝업하도록 제안합니다. 나는 이것이 거의 정확하다는 것을 알았습니다. 우선 순위가 더 높거나 스캔 한 연산자와 같으면 topStack 항목을 팝하면 마침내 내 계산이 올바르게 나왔습니다. 이 문제를 해결하는 모든 사람에게 도움이되기를 바랍니다. 귀중한 링크를 제공 한 Justin Poliey (및 fas?)에게 감사드립니다.


"항상 켜져있는"응용 프로그램이있는 경우 수학 문자열을 Google에 게시하고 결과를 구문 분석하십시오. 간단한 방법이지만 그것이 필요한지 확실하지 않지만 어떤면에서 똑똑합니다.


우선 순위가 있는 관련 질문 방정식 (표현식) 파서? 시작하는 방법에 대한 좋은 정보도 있습니다.

-아담


입력이 문자열 형식의 중위식이라고 가정하면이를 접미사 로 변환하고 한 쌍의 스택 (연산자 스택 및 피연산자 스택)을 사용하여 거기에서 솔루션을 작동 할 수 있습니다. Wikipedia 링크에서 일반적인 알고리즘 정보를 찾을 수 있습니다.


ANTLR은 매우 멋진 LL (*) 파서 생성기입니다. 나는 그것을 적극 추천합니다.


개발자는 항상 깨끗한 접근 방식을 원하고 파싱 로직을 처음부터 구현하려고 시도하며 일반적으로 Dijkstra Shunting-Yard 알고리즘 으로 끝납니다 . 결과는 깔끔하게 보이는 코드이지만 버그가있을 수 있습니다. 저는 이러한 모든 작업을 수행 하는 API 인 JMEP를 개발 했지만 안정적인 코드를 만드는 데 몇 년이 걸렸습니다.

모든 작업을 수행하더라도 이미 작업이 완료된 후에도 JavaCC 또는 ANTLR 사용으로 전환하려고 진지하게 고려하고있는 프로젝트 페이지에서도 볼 수 있습니다.


이 질문이 제기 된 후 11 년 후 : 바퀴를 재발 명하고 싶지 않다면 이국적인 수학 파서가 많이 있습니다.

산술 연산, 방정식 풀이, 미분 미적분, 적분 미적분, 기본 통계, 함수 / 공식 정의, 그래프 등을 지원하는 몇 년 전에 제가 쓴 글이 있습니다.

ParserNG 라고 하며 무료입니다.

표현식 평가는 다음과 같이 간단합니다.

    MathExpression expr = new MathExpression("(34+32)-44/(8+9(3+2))-22"); 
    System.out.println("result: " + expr.solve());

    result: 43.16981132075472

또는 변수 사용 및 간단한 표현식 계산 :

 MathExpression expr = new MathExpression("r=3;P=2*pi*r;"); 
System.out.println("result: " + expr.getValue("P"));

또는 기능 사용 :

MathExpression expr = new MathExpression("f(x)=39*sin(x^2)+x^3*cos(x);f(3)"); 
System.out.println("result: " + expr.solve());

result: -10.65717648378352

또는 주어진 지점에서 미분을 평가하려면 (수치가 아닌 기호 미분을 수행하므로 정확도가 수치 근사 오류에 의해 제한되지 않습니다) :

MathExpression expr = new MathExpression("f(x)=x^3*ln(x); diff(f,3,1)"); 
System.out.println("result: " + expr.solve());

 result: 38.66253179403897

x^3 * ln(x)x = 3에서 한 번 차별화 됩니다. 지금은 미분 할 수있는 횟수가 1 회입니다.

또는 수치 적분의 경우 :

MathExpression expr = new MathExpression("f(x)=2*x; intg(f,1,3)"); 
System.out.println("result: " + expr.solve());

result: 7.999999999998261... approx: 8

이 파서는 상당히 빠르며 다른 많은 기능이 있습니다.

Objective C에 대한 바인딩을 통해 Swift로 이식하는 작업이 완료되었으며 다른 반복적 사용 사례 중에서 그래프 응용 프로그램에 사용했습니다.

면책 조항 : ParserNG는 내가 작성했습니다.

참조 URL : https://stackoverflow.com/questions/114586/smart-design-of-a-math-parser

반응형