2014-06-15 13 views
6

Làm thế nào để viết số học đa cấp đúng trong Ruby? Trước đây, tôi đã thử một cái gì đó như y, sau đó tôi nhận ra có cái gì đó sai trái với mã đó. Tôi cần phải viết số học nhiều bậc do phương trình rất dài của tôi.Viết số học đa số trong Ruby

a = 5 
b = 5 

x = (a + b)/2 

puts x # 5, as expected 

y = (
     a 
     + b 
    )/
    2 

puts y # 2, what happened? 
+0

không có ngoại lệ, // dấu nhận xét là sai, xin lỗi, nó chỉ để làm rõ đầu ra của chương trình. Đã chỉnh sửa. Cảm ơn bạn đã sửa. – waza

Trả lời

5

Trình phân tích cú pháp Ruby sẽ giả định một câu lệnh đã kết thúc nếu có vẻ như nó đã kết thúc ở cuối dòng.

Những gì bạn có thể làm ngăn chặn điều đó là để lại các toán tử số học ngay trước khi một dòng mới, như thế này:

a = 1 
b = 2 
c = a + 
    b 

Và bạn sẽ nhận được kết quả bạn mong đợi.

+3

Hoặc bạn cũng có thể ngăn phân tích cú pháp kết thúc câu lệnh bằng ký tự '\\' (dấu gạch chéo ngược) theo sau dòng mới. –

+0

Câu trả lời này không cung cấp công việc xung quanh – Ven

+1

** một tuyên bố đã kết thúc ... nếu có vẻ như nó đã kết thúc ở cuối dòng ** gần như là một thuật toán. Nó không giải thích bất cứ điều gì. – sawa

2
(
    expr1 
    expr2 
) 

là trên thực tế, trong Ruby, giống như

(expr1; expr2) 

mà chỉ thực hiện biểu thức đầu tiên (đối với tác dụng phụ) và trả về một giây (còn sau khi đánh giá nó)

+0

Vì vậy, nó không thể viết arithmetics multiline? – waza

+0

@ fidz.id Có thể. Maurício Linhares đã mô tả cách trả lời của anh ta, đúng 100%. –

+0

Được thăng hạng vì nó không xứng đáng được hưởng ưu đãi của ai đó. Ven là đúng mã OP được hiểu là '(a; + b)/2 == (5; 5)/2 == 5/2 == 2' - phân chia số nguyên. –

2

Hãy thử suy nghĩ về "kỳ vọng" của thông dịch viên, và nhớ rằng trong ruby ​​EVERYTHING là một biểu thức (có nghĩa là mọi thứ đều đánh giá một giá trị nào đó, thậm chí xây dựng bằng ngôn ngữ khác được coi là "đặc biệt" -elses, vòng lặp, etcettera).

Vì vậy:

y = ( #1 
    a  #2 
    + b  #3 
)/  #4 
2   #5 

Tại dòng 1, chúng tôi bắt đầu khai báo của một biến, và dòng kết thúc với một mở (pending) ngoặc. Trình thông dịch mong đợi phần còn lại của định nghĩa, vì vậy nó sẽ chuyển sang dòng tiếp theo tìm kiếm giá trị VALUE để gán cho var y.

Tại dòng 2, thông dịch viên tìm biến số a, nhưng không có dấu ngoặc đơn kèm theo. Nó đánh giá a, có giá trị 5 và vì dòng 2 là một biểu thức hoàn toàn hợp lệ, trình thông dịch hiểu rằng biểu thức này đã hoàn thành (vì trong Ruby một dòng mới OFTEN có nghĩa là chỉ báo cuối biểu thức). Vì vậy, cho đến nay nó đã tạo ra một giá trị 5, nhưng kỳ vọng duy nhất nó vẫn có là nó phải khớp với dấu ngoặc đơn kèm theo.

Nếu sau đó thông dịch viên đã tìm thấy dấu ngoặc đơn kèm theo, nó sẽ gán giá trị a (i.e. 5) cho biểu thức dấu ngoặc đơn (vì mọi thứ phải có giá trị và giá trị cuối cùng được sử dụng).

Khi thông dịch viên đạt đến dòng 3, nó tìm thấy một biểu thức ruby ​​hoàn toàn hợp lệ khác, + b. Kể từ + 5 (5 là giá trị biến số b) là một khai báo số nguyên VALID trong ruby, trình thông dịch coi nó là độc lập, không liên quan đến số 5 trước đó được đánh giá cho biến a (hãy nhớ, nó không có kỳ vọng khác, ngoại trừ một cho dấu ngoặc đơn). Nói ngắn gọn, nó sẽ lấy đi giá trị thu được cho a và chỉ sử dụng giá trị thu được với + b. Trong dòng tiếp theo, nó tìm thấy dấu ngoặc đơn kèm theo, và do đó biểu thức dấu ngoặc đơn được gán giá trị được tạo cuối cùng, là một 5 được tạo ra bởi biểu thức + b.

Vì trên dòng 4 người thông dịch tìm thấy /, nó (chính xác) hiểu nó như là phương pháp chia của một số nguyên, vì nó đã tạo ra một số nguyên đến nay (int 5)! Điều này tạo ra kỳ vọng cho các đối số có thể có của phương thức, mà nó tìm thấy trên dòng 5. Biểu thức được đánh giá kết quả là y = 5/2, bằng 2 trong phân chia số nguyên. Vì vậy, về cơ bản, đây là những gì người phiên dịch đã làm:

y = ( # Ok, i'm waiting for the rest of the parenthesis expression 
    a # cool, a has value 5, if the parenthesis ends here, this is the value of the expr. 
    + b # Oh, but now I found + b, which has value + 5, which evaluates to 5. So now this is the last value I have evaluated. 
)/ # Ok, the parenthesis have been closed, and the last value I had was a 5. Uow, wait, there is a slash/there! I should now wait for another argument for the/method of the 5 I have! 
    2  # Found, let's make y = 5/2 = 2! 

Vấn đề ở đây là trên đường dây # 2, bạn nên đã để lại một kỳ vọng cho người phiên dịch (chính xác như bạn còn lại trên dòng 4 với phương pháp /) , mà bạn đã không!

Câu trả lời của @ Maurício Linhares gợi ý chính xác này:

y = (
    a + 
    b 
)/
2 

Bằng cách di chuyển phương pháp + đến cuối dòng 2, bạn nói với người phiên dịch rằng biểu hiện của bạn vẫn chưa hoàn thành! Vì vậy, nó giữ mong đợi và tiến tới dòng # 3 để tìm toán hạng đúng của biểu thức (hoặc, chính xác hơn trong Ruby, một đối số cho phương thức +: D).

Các công trình tương tự với chuỗi nối:

# WRONG, SINCE + "somestring" is not a valid stand-alone expression in ruby  
str = "I like to" 
    + " move it!" 
# NoMethodError: undefined method `[email protected]' for " move it!":String 

# CORRECT, by leaving the + sign as last statement of the first line, you 
# keep the 'expectation' of the interpreter for the next 
# argument of the + method of the string object "I like to" 
str = "I like to" + 
    " move it!" 
# => "I like to move it!" 

Sự khác biệt là trong mã của bạn không có lỗi ném, vì + b thực sự là một biểu thức hợp lệ.

Tôi hy vọng câu trả lời của tôi hữu ích khi mang lại cho bạn một số trực giác tại sao nó không hoạt động như mong đợi, xin lỗi nếu tôi không súc tích :)