Có ngôn ngữ lập trình nào trong đó 1/6 hoạt động giống như 1.0 / 6.0 không?


11

Trong khi tôi đang lập trình trong C ++ vài ngày trước, tôi đã mắc lỗi này (rằng tôi có lịch sử tạo ra nó!). Trong một phần của mã của tôi, tôi đã có 1/6 và tôi đã mong đợi nó là 0.16666666666, đây không phải là trường hợp. Như bạn đã biết kết quả là 0 - C, C ++, Java, Python, tất cả đều hoạt động giống nhau.

Tôi đăng nó trên trang Facebook của mình và bây giờ có tranh luận về việc nếu có một ngôn ngữ lập trình nơi 1/6hành xử giống như 1.0/6.0.


5
Haskell. 1/6 = 0.16666666666666666
t123

PowerShell tạo 0.166666666666667, điều làm tôi ngạc nhiên vì 1 là số nguyên. Tôi muốn có một số ngôn ngữ .NET khác tạo ra giá trị mà bạn mong đợi.
JohnL

Về lý thuyết, có một số lượng không giới hạn trong số họ .. Đây là một thứ khác: Rebol , cũng như các công cụ phái sinh như Orca, Red, v.v. >> 1 / 6->== 0.166666666666667
Izkata

Lua làm điều này. Nó chỉ có một loại Số duy nhất , thường giống với số C của đôi.
Machado

Trong Clojure 1/6thực sự là 1/6 (loại phân số), mà bị ép buộc Double, là 1.66666 ...
kaoD

Câu trả lời:


17

Có phải mọi người đã quên Pascal?

1/6năng suất 0.1666666...(cho bất cứ độ chính xác nào được hỗ trợ).

1 div 6 sản lượng 0

Người ta tranh cãi liệu quy tắc C có phải là một sai lầm hay không. Hầu như tất cả các toán tử số học của C, trong đó các toán hạng cùng loại, mang lại kết quả cùng loại. Có một cái gì đó để nói về tính nhất quán.

Hơn nữa, vì C chủ yếu nhắm vào mã cấp hệ thống, hầu hết các chương trình C hoàn toàn không sử dụng dấu phẩy động. Tại một thời điểm, việc vô tình thêm mã dấu phẩy động vào một chương trình mà không cần nó có thể là một vấn đề nghiêm trọng. Đó có lẽ vẫn là trường hợp, đối với các hệ thống nhúng nhỏ - một lần nữa, là mục tiêu chính của C.

Trong hầu hết các chương trình C, việc chia số nguyên có thể chỉ là những gì bạn muốn.

Nếu 1 / 6mang lại kết quả dấu phẩy động trong C, thì:

  • Nó sẽ là một sự không nhất quán trong ngôn ngữ.
  • Tiêu chuẩn này sẽ phải thực hiện một sự lựa chọn tùy ý dấu chấm động loại để sử dụng cho kết quả ( doublecó vẻ như sự lựa chọn tự nhiên, nhưng bạn có thể thích sự chính xác thêm long double)
  • Ngôn ngữ vẫn sẽ phải có một hoạt động để phân chia số nguyên; thực hiện bổ sung dấu phẩy động và sau đó cắt ngắn có thể sẽ không đủ tốt.

C có thể đã cung cấp các toán tử riêng cho hai loại phép chia, nhưng điểm thứ hai ở trên vẫn sẽ được áp dụng: loại nào trong ba loại dấu phẩy động sẽ được sử dụng cho kết quả? Và vì nó đủ dễ dàng để có được phép chia điểm trôi nổi nếu bạn cần nó (sử dụng hằng số dấu phẩy động cho một hoặc cả hai toán hạng, hoặc chuyển một hoặc cả hai toán hạng thành loại dấu phẩy động), rõ ràng nó không phải là ' t coi đó là quan trọng.

Trong phiên bản 1974 của hướng dẫn sử dụng C (tức là 4 năm trước khi xuất bản phiên bản đầu tiên của K & R), Ritchie thậm chí không đề cập đến sự nhầm lẫn có thể xảy ra:

Các nhị phân / toán tử chỉ ra sự phân chia. Các cân nhắc cùng loại như áp dụng cho phép nhân

trong đó nói rằng nếu cả hai toán hạng là loại inthoặc char, kết quả là loại int.

Vâng, đó là một nguồn gây nhầm lẫn cho một số lập trình viên C, đặc biệt là người mới bắt đầu - nhưng C không được chú ý vì rất thân thiện với người mới.


5
Pascal. Nhận thông tin chi tiết ngay trước khi C hiểu sai. ™
Mason Wheeler

Và sau đó Algol là một sự cải tiến so với những người kế nhiệm của nó (về số lượng cả C và Pascal).
Lập trình viên

Pascal - làm cho các chi tiết đúng (cho hoặc lấy hệ số 10)
Martin Beckett

1
Tôi ban đầu viết 1.666666..., đó là rõ ràng sai. Lý do khập khiễng của tôi là chương trình thử nghiệm Pascal mà tôi đã viết1.6666666666666667E-0001
Keith Thompson

16

Thực tế hành vi này đã được thay đổi trong Python 3 và bây giờ nó hoạt động như bạn mong đợi ( //hiện được sử dụng để phân chia số nguyên).


Cảm ơn. Bất kỳ ngôn ngữ lập trình nào khác bạn có trong tâm trí của bạn? Gia đình cơ bản có thể?
Pouya

1
@Pouya: Hành vi này là tiêu chuẩn cho gia đình Pascal. /luôn tạo ra một giá trị dấu phẩy động và một toán tử riêng ( div) được sử dụng để phân chia số nguyên.
Mason Wheeler

13

Trong số các ngôn ngữ nổi bật, JavaScript. 1.0 / 6.0 = 1/6 = 0.16666666666666666.

Tôi không thấy điều này là đáng ngạc nhiên. Như một quy tắc của ngón tay cái, nếu một ngôn ngữ phân biệt giữa các kiểu số nguyên và dấu phẩy động, chia hai số nguyên sẽ mang lại một số nguyên rút gọn thay vì float. Nếu không, nhiều khả năng nó sẽ mặc định cho các phép toán dấu phẩy động. Đây phải là hành vi dự kiến ​​về phía lập trình viên.

Chỉ cần lưu ý rằng có những thứ bổ sung cũng có thể được chơi ở đây, như toán tử phân chia số nguyên riêng biệt đã được đề cập hoặc đúc kiểu ẩn.


6
Đây không phải là "một quy tắc của ngón tay cái". Đó là quy tắc của C và một số ít ngôn ngữ sao chép một cách mù quáng những sai lầm của C.
Mason Wheeler

4
@MasonWheeler: FORTRAN có "sao chép sai lầm của C" không? Cá nhân tôi tin rằng các ngôn ngữ được thiết kế tốt nên sử dụng các toán tử riêng biệt để phân chia rút ngắn so với phân chia số lượng nguyên gần đúng (và cả btw, cho giá trị và đẳng thức tham chiếu), nhưng quyết định thiết kế trong thời của FORTRAN có lẽ là hợp lý. Điều đó không có nghĩa là mọi ngôn ngữ nên làm mọi thứ theo cách FORTRAN đã làm trong những năm 1950.
supercat

3
Các ngôn ngữ cấp thấp hơn cần thực hiện những phân biệt này. Cấp độ cao hơn / ngôn ngữ động thường tốt hơn nếu không có chúng. Đó là một sự đánh đổi trong thiết kế. Tôi đánh giá cao việc chỉ có một công cụ xây dựng / loại Số câm lớn trong JS, nhưng tôi tưởng tượng rằng tôi cảm thấy JS bị thiếu khi cố gắng viết một công cụ 3D hiệu suất cao mà không kiểm soát loại nghiêm ngặt hơn. JS có thể có tiện ích chồng chéo với các ngôn ngữ khác nhưng tôi không nghĩ có ai sẽ coi đó là một goto để viết các công cụ hiệu suất cao gần giống với chrome.
Erik Reppen

2
Toán học bên ngoài lập trình xem xét các quy tắc chỉ số nguyên để phân chia.
Erik Reppen

5
@MasonWheeler: Lập trình không phải là toán học thuần túy. Về mặt toán học, 1/6 là một số hữu tỷ và không thể được biểu diễn chính xác bằng số dấu phẩy động nhị phân. Biểu diễn chính xác duy nhất là tỷ lệ với mẫu số sáu lần tử số.
kevin cline

7

Có nhiều ngôn ngữ trong đó ((1/6)*6)kết quả là 1, không phải bằng 0. Ví dụ: PL / SQL, nhiều phương ngữ BASIC, Lua.

Vô tình, trong tất cả các langau 1/6 kết quả là .166666667 hoặc 0.16666666666667 hoặc một cái gì đó tương tự. Tôi đã chọn ((1/6) * 6) == 1 biến thể để loại bỏ những khác biệt nhỏ đó.


7
Đó không phải là câu hỏi.
Roc Martí

20
Vô tình, trong tất cả các langau 1/6 kết quả là .166666667 hoặc 0.16666666666667 hoặc một cái gì đó tương tự. Tôi đã chọn ((1/6)*6)==1biến thể để loại bỏ những khác biệt nhỏ đó, nhưng có vẻ như tôi đã đánh giá quá cao các kỹ năng toán học của một số người.
user281377

1
@ RocMartí vâng, thực sự là ...
MattDavey

1
Tôi sẽ ngạc nhiên khi thấy (1.0 / 6.0) * 6 chính xác bằng 1! Việc làm tròn kết quả của (1.0 / 6.0) sẽ dẫn đến một sự khác biệt nhỏ. (Mặc dù sẽ có một vài ngôn ngữ mặc định có độ chính xác vô hạn)
Sjoerd

1
@Sjoerd: Thật ra không quá ngạc nhiên khi nó chính xác. Xem xét trong thập phân kịch bản 1/11 * 11 với tất cả các giá trị chính xác đến năm con số quan trọng. Giá trị của 1/11 là 9.0909 * 10 ^ -2. Nhân với 11 và một người sẽ nhận được 99.9999 * 10 / -2 trước khi làm tròn. Làm tròn đến năm con số có ý nghĩa và kết quả sẽ là 1.0000 * 10 ^ 0. Lưu ý rằng điểm mấu chốt là mantissa của 1/6 là "... 0101010101 ...". Nếu bit cuối cùng của biểu diễn là "1", nhân nó với sáu và làm tròn sẽ mang lại 1. Nếu bit cuối cùng bằng 0, thì không.
supercat

3

Haskell coi 1/6 và 1.0 / 6.0 là giống hệt nhau 0.16666666666666666. Nó cũng biểu hiện 1 / 6.0 và 1.0 / 6 là cùng một giá trị.

Điều này là do các loại số cơ bản trong Haskell không hoàn toàn giống với các ngôn ngữ khác. Phân chia số nguyên thực sự có phần ... phức tạp.


2

Vâng, Perl nào. Một lớp lót

perl -e '$x=1/6;print "$x\n";'

kết quả trong đầu ra của:

0.166666666666667

Tôi tin rằng PHP hoạt động theo cùng một cách.

Chỉnh sửa để thêm: Tôi cũng tin rằng một điều kiện cần (nhưng không đủ) dành 1/6 == 1.0/6.0cho ngôn ngữ được đề cập sẽ được gõ yếu.


Tại sao quái vật đánh máy yếu (bất cứ điều gì được cho là có nghĩa) là cần thiết? Chỉ cần định nghĩa / đến (cũng) có nghĩa là phân chia float trong trường hợp cả hai đối số là số nguyên.

1
@delnan - en.wikipedia.org/wiki/Weak_typing Tôi cho rằng nó có thể là có thể có một ngôn ngữ mạnh mẽ gõ trong đó /được tự động quá tải tùy thuộc vào loại của các đối số, nhưng điều đó có vẻ như một sự vi phạm các nguyên tắc của sự ngạc nhiên nhỏ nhất để tôi ...

2
Gõ yếu / mạnh là không xác định (như wiki cũng ngụ ý), xin vui lòng tránh nó và được cụ thể. Tôi lấy định nghĩa của bạn cấm chuyển đổi ngầm, nhưng không phải là đa hình ad-hoc? Nếu vậy, hãy xem xét Haskell, không có chuyển đổi ngầm định nhưng được thực hiện khá tốt (như trong, hoạt động 99% thời gian và có thể được hiểu bởi người phàm) đa hình số. Và tại sao điều này sẽ gây ngạc nhiên? Nó sẽ đáng kinh ngạc hơn nhiều (không nói khó chịu) với tôi nếu tôi phải thêm một số dấu chấm vào mỗi phiên bản của bất kỳ toán tử nào, tùy thuộc vào độ chính xác chính xác mà tôi muốn.

2
@JackManey Tôi nghĩ với hầu hết những người mới tham gia, điều đáng ngạc nhiên hơn là 1/2 nên bằng 0 nếu chia hai số nguyên cho kết quả gấp đôi. Sau khi tất cả các số nguyên không đóng dưới sự phân chia trong toán học. Cũng như delnan chỉ ra, Haskell là một ví dụ về ngôn ngữ được gõ mạnh trong đó / trên hai số nguyên, không tạo ra một số nguyên. Và Python 3 là một cái khác.
sepp2k

1
Ngôn ngữ Haxe được gõ mạnh (mặc dù được suy ra), và nó không có phân chia số nguyên, chỉ nổi. Vì vậy, có bạn đi.
K.Steff

2

Trong Squeak Smalltalk /trên các số nguyên tạo các đối tượng Phân số. Vì vậy, trong khi điều này không giống như phân chia float, vẫn (1/6)*6trả về 1.


Trong tất cả các dẫn xuất của Smalltalk-80 (nghĩa là gần như tất cả các Smalltalk). Amber là một trong những trường hợp ngoại lệ đương đại (có thể hiểu được, được biên dịch thành JavaScript).
Herby

2

Có, tôi vừa kiểm tra TI-99 / 4A được tích hợp trong TI BASIC . Vì nó coi tất cả các biểu thức số là dấu phẩy động, nên phép toán chia cũng là dấu phẩy động.

 TI BASIC READY
>PRINT 1/6
  .1666666667

>


2

MATLAB. Chữ số được nhân đôi theo mặc định.

>> 1/6
ans =
    0.1667

2

Clojure sử dụng phân số theo mặc định. Nó không giống như 1.0 / 6.0, nhưng bạn có thể chuyển đổi sang floathoặc doublekhi bạn cần.

user=> (/ 1 6)
1/6
user=> (* (/ 1 6) 2)
1/3
user=> (pos? (/ 1 6)) ; Is 1/6 > 0?
true
user=> (float (/ 1 6))
0.16666667

1

Đáng ngạc nhiên, nó dường như hoạt động đúng trong Windows PowerShell (phiên bản 3) .

PS C:\> 1.0 / 6.0
0.166666666666667

PS C:\> 1/6
0.166666666666667

Cũng có vẻ hoạt động trong Python 3 như sepp2k đã đề cập. Hai ngôn ngữ khác tôi đã có sẵn trên REPL, Scala và Ruby, cả hai đều phân chia số nguyên và mang lại 0.


0

Ngôn ngữ Rexx luôn tạo ra một câu trả lời đúng về mặt số học. Ví dụ: 5/2 = 2,5. Rexx là một ngôn ngữ tuyệt vời chưa được sử dụng đủ. Về lý thuyết, khi một trình biên dịch không thể xác định những gì bạn muốn, tốt hơn là làm toán chính xác, tuy nhiên, điều này có thể không hiệu quả. Rexx cũng cung cấp toán tử //.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.