2014-09-01 13 views
5

Tôi có cảm giác rằng đây chỉ là một lỗi vô hại nhưng tôi vẫn muốn hiểu những gì đang xảy ra.Tại sao Chrome sản xuất 1099 chữ số sau dấu chấm cho (.1) .toString (3)?

Tôi đang chơi với một số mã để hiển thị Peano curve trên canvas có liên quan đến việc biểu diễn tọa độ logic trong cơ sở 3 khi tôi nhận thấy một hàm đã trả về chuỗi dài vô lý trong Chrome. Nhìn kỹ hơn, nó chỉ ra rằng sự biểu hiện

(.1).toString(3) 

đánh giá trong Chrome để

0,002200220022002200220022002200220100002100210000110101000202201120201212110212202011212000102021022210120112001022101010120202020022102010100200210110010000202221001022002202102122102110002012010220202020011000222022001200102102202000112022010100102211212012122021012212120012120012221210011021010220200001202121120022222110111121112201212111120221121001002221210000221022021012220020112022001121012011001112000001101100101011002201210200110202021021120211100100210120010202222111221201201100002211002202000110011221210 2102100111000222211012211220200112120002100121210000222002201120220111022021120022101112201220001101012112201211010010110122011201120022210102021100002000121020120001112122222220201200220012211122001022022001222011221100212001100010200001211022021120210222110022221202002120011210220012001022112012202110101212100011220000220200122222102201100202101012110201221202211220201111021112112201120101121122212112220211110002020120201022022121210120002202021212000101222221101122201001100021211101012101011202020110010112202201201001020212002021112020021121202000000222122210022012001201

như đã thấy ở đây: http://jsfiddle.net/zvp8osm8/

Đối với những gì tôi có thể nói, chỉ có 33 chữ số đầu tiên sau dấu chấm có ý nghĩa trong trường hợp này, phần còn lại trông giống như rác ngẫu nhiên mà không có một mẫu dễ nhận biết. Kết quả tương tự với 1099 (!) Chữ số sau khi dấu chấm được tạo cho các căn cứ khác nhau và số mũ quá giống như (10000000000.1).toString(3) hoặc (.7).toString(7). Các giá trị khác như (.5).toString(3) cũng tạo ra các chuỗi dài, nhưng tất cả các chữ số đều có ý nghĩa.

Các trình duyệt khác ngoại trừ Opera chỉ tạo ra số chữ số hợp lý trong mọi trường hợp, điều này khiến tôi nghĩ rằng sự cố nằm trong công cụ Javascript của Chrome.

Tôi có hai câu hỏi bây giờ:

  • Tại sao các đại diện của số thập phân trong cơ sở 3 chứa rất nhiều chữ số không đáng kể trong Chrome?
  • Các chữ số ngẫu nhiên có thể đến từ đâu?
+0

Căn cứ 5, 7, 9, v.v. cũng tạo ra kết quả tương tự. Có lẽ logic đằng sau đó là giá trị cơ bản lẻ. – VisioN

+0

Một người nào đó sẽ lấp đầy bạn tốt hơn, nhưng tôi sẽ nguy hiểm đoán rằng đó là bởi vì không có cách chính xác để đại diện cho 0,1 trong nhị phân. (xem lỗi dấu phẩy động) – Mardoxx

Trả lời

5

Đối với trường hợp cụ thể bạn hiển thị, có vẻ như các chữ số được tạo bằng thuật toán ngây thơ sau, bắt đầu bằng x = .1.

  1. Multiply x bởi 3.
  2. Trích xuất số nguyên và các bộ phận phân đoạn của kết quả.
  3. Xuất phần nguyên làm chữ số và thay thế x bằng phần phân số.
  4. Lặp lại các bước từ 1 đến 3 cho đến khi chán (hoặc cho đến khi đạt được một số giới hạn đặt trước).

Điều này sẽ hoạt động tốt về mặt toán học, nhưng trong thế giới của dấu phẩy, điều này hoàn toàn vô nghĩa, bởi vì nhân 3 và vòng tiếp theo với số dấu phẩy động gần nhất có khả năng giới thiệu một lỗi nhỏ, và sau 30 chữ số, do đó, lỗi đã hoàn toàn làm ngập các chữ số gốc và chúng tôi chỉ nhận được rác.

Có lẽ cũng có một số cách xử lý các chữ số trước điểm cho trường hợp số đầu lớn hơn 1.0 với giá trị tuyệt đối, nhưng không có đầu ra mẫu, tôi sẽ không đoán thuật toán đó là gì.

Để biện minh cho điều trên, đây là một số mã trong Python có kết quả khớp chính xác được đưa ra trong câu hỏi. Ở đây, modf là hoạt động trích xuất các phần phân đoạn và tích phân của một phao Python.

>>> from math import modf 
>>> x = 0.1 
>>> digits = [] 
>>> for _ in xrange(1099): 
...  x, digit = modf(3.0 * x) 
...  digits.append(str(int(digit))) 
... 
>>> print('0.' + ''.join(digits)) 

Và kết quả:

0,00220022002200220022002200220022010000210021000011010100020220112020121211021220201121200010202102221012011200102210101012020202002210201010020021011001000020222100102200220210212210211000201201022020202001100022202200120010210220200011202201010010221121201212202101221212001212001222121001102101022020000120212112002222211011112111220121211112022112100100222121000022102202101222002011202200112101201100111200000110110010101100220121020011020202102112021110010021012001020222211122120120110000221100220200011001122121021021001110002222110122112202001121200021001212100002220022011202201110 22021120022101112201220001101012112201211010010110122011201120022210102021100002000121020120001112122222220201200220012211122001022022001222011221100212001100010200001211022021120210222110022221202002120011210220012001022112012202110101212100011220000220200122222102201100202101012110201221202211220201111021112112201120101121122212112220211110002020120201022022121210120002202021212000101222221101122201001100021211101012101011202020110010112202201201001020212002021112020021121202000000222122210022012001201

này nên trả lời một câu hỏi của bạn: cụ thể là nơi các chữ số ngẫu nhiên đến từ. Tôi không thể trả lời câu hỏi tại sao Chrome chọn đầu ra quá nhiều chữ số.

+0

Mỗi số dấu phẩy động lớn hơn 1/N chính xác được thể hiện trong 53+ lg (N) hoặc ít chữ số hơn trong bất kỳ số chẵn nào, nhưng không có số dấu phẩy động nào có phần phân số khác 0 được thể hiện chính xác ở bất kỳ số chữ số nào trong bất kỳ số lẻ nào. Tôi đoán Chrome sẽ lặp lại cho đến khi phần còn lại trở thành 0 (điều này sẽ xảy ra với các số chẵn, và sẽ không xảy ra với các căn cứ lẻ) hoặc cho đến khi nó "chán" [nhấn "giới hạn" an toàn trên vòng lặp] . – supercat

2

Đầu tiên, số .1 phải được chuyển đổi thành dấu phẩy động, được biểu thị bằng nhị phân. Trong dạng nhị phân, .1 không thể được biểu diễn chính xác, do đó, sẽ có một số lỗi ở các số thứ tự thấp. Điều này tương tự với việc cố gắng biểu diễn 1/7 bằng số thập phân: đó là chuỗi lặp lại .142857 142857 ...; bất cứ nơi nào bạn kết thúc nó, bạn sẽ bị mất chính xác.

Khi điều này sau đó được chuyển đổi thành cơ sở 3, lỗi trong các chữ số đó dẫn đến sự ngẫu nhiên mà bạn đang thấy.

+0

Tuy nhiên, cơ số 2 hoặc 4 sẽ hiển thị số lượng "hữu hạn" của số cho cùng một giá trị float. Nó có vẻ liên quan đến căn cứ bằng cách nào đó. – VisioN

+0

Biểu diễn bên trong là cơ số 2. Vì vậy, chỉ sao chép các bit từ biểu diễn bên trong, có một số bit hữu hạn. – Barmar

+2

@VisioN Radix 2 và 4 đều có thuộc tính mà bất kỳ phần tử chấm dứt nào cũng có thể được biểu diễn bằng một phần cuối 10 phần cuối. Đó là bởi vì yếu tố chính duy nhất, 2, cũng là một yếu tố của 10. 3, mặt khác, không phải là một yếu tố của 10. –

1

Bắt đầu với ECMAScript 5.1 spec, cụ thể là 15.7.4.2 Number.prototype.toString([radix])9.8.1 ToString Applied to the Number Type:

Thuật toán chính xác để chuyển đổi số thành chuỗi là phụ thuộc vào triển khai thực hiện nếu cơ số không phải là 10 (xem 15.7.4.2), tuy nhiên, nó được coi là một thuật toán tổng quát của thuật toán được nêu trong 9.8.1.
Điều này có nghĩa là mỗi trình duyệt (và mọi triển khai khác) đều miễn phí để chọn xem chúng có muốn cung cấp độ chính xác tiêu chuẩn (tối đa 21 chữ số) hay không.

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