2011-01-24 43 views
5

Đây là một điều thú vị. Bất cứ ai cũng có một RegEx tốt để chuyển đổi tất cả (đầu tiên)^(giây) thành Math.pow ((đầu tiên), (thứ hai))?RegEx cho^b thay vì pow (a, b)

EDIT:

Điều tốt nhất tôi có cho đến nay là

s = s.replace(/((?:\d+\.?\d*)|\w+|\((?:(?:[^\(\)]*(?:\([^\(\)]*\)))*)\))\s*\^\s*((?:\d+\.?\d*)|\w+|\((?:(?:[^\(\)]*(?:\([^\(\)]*\)))*)\))/g, 'Math.pow($1, $2)') // replace expression^expression with Math.pow($1, $2) 

Những câu trả lời cho đến nay chưa đủ nói chung. Họ không bao gồm một cái gì đó như (var1 + var2)^2 cho phép một mình (var1 * (var2 + var3))^2

Giải pháp sẽ phải làm việc với dấu ngoặc đơn.

Bạn có thể sử dụng strfriend.com để giúp trực quan hóa regex khi bạn thực hiện. Đó là những gì tôi đã làm.

+3

Và gần nhất bạn có ngay bây giờ là ...? – Oswald

+4

Điều gì nên 'a * b^c' chuyển đổi thành? 'a^b + c'? 'a^b^c'? –

+5

Điều này không thể thực hiện với regex bình thường. Nó đòi hỏi đệ quy tùy ý. Nếu bạn muốn một câu trả lời tôi đề nghị bạn nâng cao tiền thưởng, đây là một vấn đề khá liên quan. – kelloti

Trả lời

11

này không thể được thực hiện với regex (ít nhất là không phải không có nhiều nỗ lực). Bạn phải xem xét các lớp khác nhau của dấu ngoặc đơn, không thể xử lý bằng biểu thức chính quy đơn giản. Tôi đề nghị tìm một thư viện có khả năng phân tích biểu thức toán học. Hoặc bạn sẽ phải hạn chế các biểu thức có thể đối với một cái gì đó bạn có thể xử lý với một regex đơn giản.

Có khả năng xác định các nhóm chụp được đặt tên và cân bằng trong cụm từ thông dụng có thể được sử dụng (được trả lời ngược lại) trong cùng một cụm từ thông dụng. Với điều này, bạn sẽ phải xác định tập hợp con mong muốn của cú pháp toán và cả hai nắm bắt cho các tham số. Tôi đề nghị bạn không nên tái tạo lại bánh xe và sử dụng một thư viện JS.

http://snippets.dzone.com/posts/show/2207

+3

Mattias ở ngay tại đây; nếu bạn có một ngôn ngữ với các cấu trúc lồng nhau như parens, thì một ngôn ngữ thông thường sẽ không cắt nó - trên thực tế, nó có trong định nghĩa của 'ngôn ngữ thông thường'. Tốt hơn để bắt đầu viết một trình phân tích cú pháp, hoặc tìm một trong số rất nhiều ở đó. –

2

Bạn có thể sử dụng String.replace:

> s = "hello 2^3 pow!" 
> s.replace(/(\d+)\^(\d+)/, "Math.pow($1, $2)") 
"hello Math.pow(2, 3) pow!" 
1

Giả sử bạn muốn chuyển đổi file nguồn hoặc một cái gì đó như thế, phải mất một kịch bản perl chạy qua các tập tin nguồn của bạn và sử dụng Math::Expression::Evaluator::Parser. Từ bản tóm tắt:

use Math::Expression::Evaluator::Parser; 

my $exp = '2 + a * 4'; 
my $ast = Math::Expression::Evaluator::Parser::parse($exp, {}); 
# $ast is now something like this: 
# $ast = ['+', 
#   2, 
#   ['*', 
#   ['$', 'a'], 
#   4 
#   ] 
#  ]; 

Có vẻ như nó có thể xử lý số mũ một cách dễ dàng. Vì vậy, AST trong trường hợp của bạn sẽ là một cái gì đó như:

# $ast = ['^', 
#   base, 
#   exp 
#  ]; 

Bạn có thể xây dựng các biểu hiện mong muốn 'Math.pow (cơ sở, exp)' bởi (đệ quy) Lắp ráp lại một chuỗi từ 'cơ sở' và 'exp' subtrees.

Nếu bạn muốn triển khai máy tính bằng JavaScript thì bạn cần tất nhiên là JavaScript-Parser hoặc bạn có thể dựa vào máy chủ phụ trợ được triển khai bằng Math :: Expression :: Evaluator.

+0

Điều này, hoặc một câu trả lời thảo luận về việc thực hiện chức năng tương tự trong JS là câu trả lời đúng. – Incognito

1

Tin xấu: biểu thức thông thường sẽ không cắt (như nhiều câu trả lời cho biết), bạn sẽ cần phải viết một trình phân tích cú pháp cho điều này.

Tin tốt: bạn có thể tương đối dễ dàng tự làm điều này bằng hầu hết mọi ngôn ngữ bằng cách viết trình phân tích cú pháp gốc đệ quy. Tất nhiên bạn nên sử dụng lại mã hiện có càng nhiều càng tốt, nhưng mã hóa một trình phân tích cú pháp gốc đệ quy (và xem cách bạn mã hóa các quy tắc ưu tiên) có thể được đề xuất hoàn toàn cho trải nghiệm giác ngộ.

Chọn bất kỳ cuốn sách nào về xây dựng trình biên dịch và đọc một vài chương đầu tiên về phân tích cú pháp. Hãy để tôi giới thiệu this freely available book bởi Niklaus Wirth, tìm 4.1 "Phương pháp của đệ quy gốc".

0

Hãy xem Jison, trình tạo trình phân tích cú pháp Javascript.

Đặc biệt, kiểm tra của họ calculator demo

0
var caretReplace = function(_s) { 
    if (_s.indexOf("^") > -1) { 
     var tab = []; 
     var powfunc="Math.pow"; 
     var joker = "___joker___"; 
     while (_s.indexOf("(") > -1) { 
      _s = _s.replace(/(\([^\(\)]*\))/g, function(m, t) { 
       tab.push(t); 
       return (joker + (tab.length - 1)); 
      }); 
     } 

     tab.push(_s); 
     _s = joker + (tab.length - 1); 
     while (_s.indexOf(joker) > -1) { 
      _s = _s.replace(new RegExp(joker + "(\\d+)", "g"), function(m, d) { 
       return tab[d].replace(/(\w*)\^(\w*)/g, powfunc+"($1,$2)"); 
      }); 
     } 
    } 
    return _s; 
}; 
  1. console.log(caretReplace("(3*(f(x^2)-2)^2+1^5-g(2^3+1)^5)^(9-2^3)")); cho Math.pow((3*Math.pow((f(Math.pow(x,2))-2),2)+Math.pow(1,5)-Math.pow(g(Math.pow(2,3)+1),5)),(9-Math.pow(2,3))).

  2. Biểu thức toán học của bạn phải hợp lệ, với dấu ngoặc đơn mở và đóng được cân bằng tốt.

  3. Bạn có thể thay thế Math.pow bằng bất kỳ tên chức năng nào bạn muốn.

  4. Tôi đã thực hiện điều này bằng cách thay thế tất cả các dấu ngoặc đơn, từ bên trong nhất sang bên ngoài nhất, với các văn bản phi toán (___joker___0, ___joker___1, v.v.). Cuối cùng, tôi phân tích tất cả các chuỗi này theo thứ bậc, để thay thế các dấu nháy trên các biểu thức không dấu ngoặc đơn.

Các vấn đề liên quan