Điều gì gây ra lỗi làm tròn điểm nổi?


62

Tôi biết rằng số học dấu phẩy động có vấn đề chính xác. Tôi thường khắc phục chúng bằng cách chuyển sang biểu diễn thập phân cố định của số hoặc đơn giản bằng cách bỏ qua lỗi.

Tuy nhiên, tôi không biết đâu là nguyên nhân của sự thiếu chính xác này. Tại sao có nhiều vấn đề làm tròn với số float?


28
Nói chính xác, đó không thực sự là lỗi do làm tròn mà hầu hết mọi người lo lắng - thực tế là việc làm tròn dấu phẩy động nhị phân hành xử theo những cách không trực quan. Chuyển sang biểu diễn thập phân có thể làm cho việc làm tròn hoạt động theo cách trực quan hơn, nhưng đổi lại, bạn sẽ gần như luôn tăng lỗi tương đối (hoặc nếu không phải tăng dung lượng lưu trữ để bù).
Daniel Pryden

12
Nỗ lực của tôi để làm sáng tỏ những nhầm lẫn phổ biến nhất: float-point-gui.de
Michael Borgwardt

tôi nghĩ ý nghĩa của @DanielPryden là "Chuyển sang biểu diễn [điểm cố định] có thể khiến cho việc làm tròn hoạt động theo cách trực quan hơn ..." . Điều gây ra các vấn đề làm tròn, cho dù đó là số cố định hay dấu phẩy động là độ rộng từ hữu hạn của một trong hai. chỉ là, với điểm nổi, độ lớn của lỗi làm tròn thường vẫn tỷ lệ thuận với độ lớn của số được làm tròn. (ngoại trừ khi bạn nhận được số thực sự nhỏ và đến số "không chuẩn hóa".)
robert bristow-johnson

@robert: Đó không chính xác là những gì tôi đã đề cập. "Lỗi" mà hầu hết mọi người gặp phải với dấu phẩy động không liên quan gì đến dấu phẩy động, đó là cơ sở. Các phao và đôi của IEEE-754 sử dụng số mũ trong cơ sở 2, có nghĩa là các số phân số được làm tròn thành lũy thừa âm của hai (1/2, 1/16, 1/1024, v.v.) chứ không phải là lũy thừa âm 10 (1 / 10, 1/1000, v.v.) Điều này dẫn đến kết quả không trực quan như làm tròn 0,1 đến 0,000001 và các vấn đề tương tự.
Daniel Pryden

Bạn có thể thực hiện các số dấu phẩy động trong cơ sở 10 - đó là cách decimalloại của .NET hoạt động. Điểm cố định, mặt khác, là khác nhau. Miễn là phạm vi của bạn bị giới hạn, điểm cố định là một câu trả lời tốt. Nhưng phạm vi hạn chế làm cho điểm cố định không phù hợp với nhiều ứng dụng toán học và việc triển khai số điểm cố định thường không được tối ưu hóa tốt trong phần cứng.
Daniel Pryden

Câu trả lời:


82

Điều này là do một số phân số cần một số lượng rất lớn (hoặc thậm chí vô hạn) các vị trí được thể hiện mà không làm tròn. Điều này đúng với ký hiệu thập phân nhiều như nhị phân hoặc bất kỳ ký hiệu nào khác. Nếu bạn sẽ giới hạn số lượng vị trí thập phân được sử dụng cho các tính toán của mình (và tránh thực hiện các phép tính theo ký hiệu phân số), bạn sẽ phải làm tròn ngay cả một biểu thức đơn giản là 1/3 + 1/3. Thay vì viết 2/3, bạn sẽ phải viết 0.33333 + 0.33333 = 0.66666 không giống với 2/3.

Trong trường hợp máy tính, số lượng chữ số bị giới hạn bởi bản chất kỹ thuật của bộ nhớ và thanh ghi CPU. Ký hiệu nhị phân được sử dụng trong nội bộ làm tăng thêm một số khó khăn. Máy tính thường không thể biểu thị số theo ký hiệu phân số, mặc dù một số ngôn ngữ lập trình bổ sung khả năng này, cho phép tránh các vấn đề đó ở một mức độ nhất định.

Những gì mọi nhà khoa học máy tính nên biết về số học dấu phẩy động


12
Tại chỗ trên. Nhưng tôi cũng lưu ý rằng một số số kết thúc bằng số thập phân không kết thúc ở dạng nhị phân. Cụ thể 0,1 là một số định kỳ trong nhị phân và vì vậy không có số nhị phân dấu phẩy động nào có thể biểu diễn chính xác 0,1.
Jack Aidley

4
Điểm nổi không chỉ hữu ích cho nhiều vị trí thập phân. Số nguyên 32 bit chỉ có thể đếm tối đa khoảng 4 tỷ, nhưng số float 32 bit có thể lớn gần như vô hạn.
Abhi Beckert

7
Cụ thể, các phân số mà chúng ta có thể biểu thị dưới dạng số thập phân hữu hạn là các phân số có hệ số nguyên tố mẫu số chỉ chứa 2 và 5 (ví dụ: chúng ta có thể biểu thị 3/10 và 7/25, nhưng không phải là 11/18). Khi chúng ta chuyển sang hệ nhị phân, chúng ta sẽ mất hệ số 5, do đó chỉ có thể biểu thị chính xác các tỷ lệ dyadic (ví dụ 1/4, 3/128).
David Zhang

70

Về cơ bản, các lỗi làm tròn xuất phát từ thực tế là vô hạn của tất cả các số thực không thể được biểu thị bằng bộ nhớ hữu hạn của máy tính , chứ đừng nói đến một lát bộ nhớ nhỏ như một biến số dấu phẩy động , vì vậy nhiều số được lưu trữ chỉ là xấp xỉ số họ có nghĩa là đại diện.

Vì chỉ có một số giá trị giới hạn không phải là gần đúng và bất kỳ thao tác nào giữa một xấp xỉ và một số khác đều dẫn đến một xấp xỉ, các lỗi làm tròn là gần như không thể tránh khỏi .

Điều quan trọng là nhận ra khi nào chúng có khả năng gây ra sự cốthực hiện các bước để giảm thiểu rủi ro .


Ngoài những điều cốt yếu của David Goldberg , mọi nhà khoa học máy tính nên biết gì về số học dấu phẩy động (được Sun / Oracle tái bản dưới dạng phụ lục của Hướng dẫn tính toán số ) của họ, được đề cập bởi thorsten , tạp chí ACCU đã tải rất xuất sắc loạt bài viết của Richard Harris về Floating Point Blues .

Bộ phim bắt đầu với

Điện toán số có nhiều cạm bẫy. Richard Harris bắt đầu tìm kiếm một viên đạn bạc.

Con rồng lỗi số thường không được đánh thức từ giấc ngủ của anh ta, nhưng nếu tiếp cận một cách vô thức, anh ta đôi khi sẽ gây ra thiệt hại thảm khốc theo tính toán của người lập trình viên.

Đến nỗi một số lập trình viên, đã tình cờ gặp anh ta trong khu rừng của số học dấu phẩy động IEEE 754, khuyên các đồng nghiệp của họ không đi du lịch trong vùng đất công bằng đó.

Trong loạt bài viết này, chúng ta sẽ tìm hiểu về thế giới của điện toán số, đối chiếu số học dấu phẩy động với một số kỹ thuật đã được đề xuất như là sự thay thế an toàn hơn cho nó. Chúng ta sẽ biết rằng lãnh thổ của rồng thực sự vươn xa và nói chung chúng ta phải bước đi cẩn thận nếu chúng ta sợ sự chú ý tàn phá của anh ta.

Richard bắt đầu bằng cách giải thích phân loại số thực, hợp lý, không hợp lý, đại số và siêu việt. Sau đó, anh tiếp tục giải thích về đại diện của IEEE754, trước khi tiếp tục xảy ra lỗi hủy và thứ tự các vấn đề thực thi.

Nếu bạn đọc không sâu hơn điều này, bạn sẽ có một nền tảng tuyệt vời trong các vấn đề liên quan đến số dấu phẩy động.

Nếu bạn muốn biết thêm, tuy nhiên, anh tiếp tục với

Sau đó, anh ta chuyển sang cố gắng giúp bạn chữa tính toán Blues của bạn

và cuối cùng nhưng không kém phần quan trọng

Toàn bộ loạt bài viết rất đáng để xem xét, và tổng cộng 66 trang, chúng vẫn nhỏ hơn 77 trang của bài báo Goldberg .

Mặc dù loạt bài này bao gồm nhiều vấn đề tương tự, tôi thấy nó dễ tiếp cận hơn bài báo của Goldberg . Tôi cũng thấy dễ hiểu hơn những phần phức tạp hơn của bài báo sau khi đọc những bài báo trước đó của Richards và sau những bài báo đầu tiên đó, Richard rẽ vào nhiều lĩnh vực thú vị không được tờ Goldberg chạm đến.


vậy, spake ak đã đề cập trong các ý kiến:

Là tác giả của những bài viết mà tôi muốn đề cập rằng tôi đã tạo các phiên bản tương tác của chúng trên blog của mình www.thusspakeak.com bắt đầu với thusspakeak.com/ak/2013/06 .


1
Là tác giả của những bài viết mà tôi muốn đề cập rằng tôi đã tạo các phiên bản tương tác của chúng trên blog của mình www.thusspakeak.com bắt đầu với thusspakeak.com/ak/2013/06 .
do đó spake ak

Cảm ơn @ thusspakea.k. Tôi đã thêm một ghi chú vào câu trả lời của mình và những yếu tố tương tác này hoạt động rất độc đáo.
Đánh dấu gian hàng

12

Vâng, thorstenliên kết dứt khoát . Tôi sẽ thêm:

Bất kỳ hình thức đại diện sẽ có một số lỗi làm tròn cho một số số. Cố gắng biểu thị 1/3 theo dấu phẩy động của IEEE hoặc bằng số thập phân. Không thể làm điều đó một cách chính xác. Điều này vượt ra ngoài việc trả lời câu hỏi của bạn, nhưng tôi đã sử dụng quy tắc này thành công:

  • Lưu trữ các giá trị do người dùng nhập theo số thập phân (vì gần như chắc chắn họ đã nhập nó dưới dạng đại diện thập phân - rất ít người dùng sẽ sử dụng nhị phân hoặc hex). Bằng cách đó, bạn luôn có đại diện chính xác do người dùng nhập.
  • Nếu bạn phải lưu trữ phân số do người dùng nhập, hãy lưu tử số và mẫu số (cũng ở dạng thập phân)
  • Nếu bạn có một hệ thống có nhiều đơn vị đo cho cùng một số lượng (như Celsius / Fahrenheit) và người dùng có thể nhập cả hai, lưu trữ giá trị họ đã nhập và đơn vị họ đã nhập vào. Đừng thử chuyển đổi và lưu dưới dạng một đại diện duy nhất, trừ khi bạn có thể làm điều đó mà không mất độ chính xác / chính xác. Sử dụng giá trị được lưu trữ các đơn vị trong tất cả các tính toán.
  • Lưu trữ các giá trị được tạo của máy trong điểm nổi IEEE (đây có thể là các số được tạo bởi thiết bị đo điện tử, giống như cảm biến tương tự với bộ chuyển đổi A / D hoặc kết quả không tính toán của phép tính). Lưu ý rằng điều này không áp dụng nếu bạn đang đọc cảm biến qua kết nối nối tiếp và nó đã cung cấp cho bạn giá trị ở định dạng thập phân (ví dụ: 18,2 C).
  • Lưu trữ tổng số người dùng có thể xem, v.v., dưới dạng thập phân (như số dư tài khoản ngân hàng). Làm tròn một cách thích hợp, nhưng sử dụng giá trị đó làm giá trị dứt khoát cho tất cả các tính toán trong tương lai.

Tôi sẽ thêm: Cân nhắc sử dụng gói toán học có độ chính xác tùy ý như ARPREC hoặc decNumber.
Blrfl

Tôi không thập phân (trái ngược với nhị phân) có nhiều lợi ích cho các giá trị nguyên, chẳng hạn như tử số và mẫu số của một phân số. Hoặc có thể lưu trữ các giá trị nguyên chính xác và nhị phân hiệu quả hơn. Có một số chi phí trong việc chuyển đổi qua lại cho đầu vào và đầu ra, nhưng điều đó có thể bị ngập trong chi phí thực hiện I / O về mặt vật lý.
Keith Thompson

10

Những gì dường như chưa được đề cập cho đến nay là các khái niệm về một thuật toán không ổn định và một vấn đề không có điều kiện . Trước tiên tôi sẽ giải quyết vấn đề này, vì đó dường như là một cạm bẫy thường xuyên hơn đối với các nhà số học mới làm quen.

Xem xét tính toán sức mạnh của tỷ lệ vàng (đối ứng) φ=0.61803…; một cách có thể để làm điều đó là sử dụng công thức đệ quy φ^n=φ^(n-2)-φ^(n-1), bắt đầu bằng φ^0=1φ^1=φ. Nếu bạn chạy đệ quy này trong môi trường máy tính yêu thích của bạn và so sánh kết quả với các quyền hạn được đánh giá chính xác, bạn sẽ thấy sự ăn mòn chậm của các số liệu quan trọng. Đây là những gì xảy ra trong Mathicala :

ph = N[1/GoldenRatio];  
Nest[Append[#1, #1[[-2]] - #1[[-1]]] & , {1, ph}, 50] - ph^Range[0, 51]  
{0., 0., 1.1102230246251565*^-16, -5.551115123125783*^-17, 2.220446049250313*^-16, 
-2.3592239273284576*^-16, 4.85722573273506*^-16, -7.147060721024445*^-16, 
1.2073675392798577*^-15, -1.916869440954372*^-15, 3.1259717037102064*^-15, 
-5.0411064211886014*^-15, 8.16837916750579*^-15, -1.3209051907825398*^-14, 
2.1377864756200182*^-14, -3.458669982359108*^-14, 5.596472721011714*^-14, 
-9.055131861349097*^-14, 1.465160458236081*^-13, -2.370673237795176*^-13, 
3.835834102607072*^-13, -6.206507137114341*^-13, 1.004234127360273*^-12, 
-1.6248848342954435*^-12, 2.6291189633497825*^-12, -4.254003796798193*^-12, 
6.883122762265558*^-12, -1.1137126558640235*^-11, 1.8020249321541067*^-11, 
-2.9157375879969544*^-11, 4.717762520172237*^-11, -7.633500108148015*^-11, 
1.23512626283229*^-10, -1.9984762736468268*^-10, 3.233602536479646*^-10, 
-5.232078810126407*^-10, 8.465681346606119*^-10, -1.3697760156732426*^-9, 
2.216344150333856*^-9, -3.5861201660070964*^-9, 5.802464316340953*^-9, 
-9.388584482348049*^-9, 1.5191048798689004*^-8, -2.457963328103705*^-8, 
3.9770682079726053*^-8, -6.43503153607631*^-8, 1.0412099744048916*^-7, 
-1.6847131280125227*^-7, 2.725923102417414*^-7, -4.4106362304299367*^-7, 
7.136559332847351*^-7, -1.1547195563277288*^-6}

Kết quả φ^41có ý định có dấu sai và thậm chí sớm hơn, các giá trị được tính toán và thực tế cho φ^39chia sẻ không có chữ số chung ( 3.484899258054952* ^ - 9 for the computed version against the true value7.071019424062048 *^-9). Do đó, thuật toán không ổn định và người ta không nên sử dụng công thức đệ quy này trong số học không chính xác. Điều này là do bản chất vốn có của công thức đệ quy: có một giải pháp "phân rã" và "đang phát triển" cho đệ quy này và cố gắng tính toán giải pháp "phân rã" bằng giải pháp chuyển tiếp khi có một giải pháp "tăng trưởng" thay thế đang cầu xin cho đau buồn số. Do đó, người ta phải đảm bảo rằng các thuật toán số của mình ổn định.

Bây giờ, về khái niệm của một vấn đề không có điều kiện : mặc dù có thể có một cách ổn định để làm một cái gì đó bằng số, nhưng rất có thể đó là vấn đề bạn vừa không thể giải quyết bằng thuật toán của mình. Đây là lỗi của chính vấn đề chứ không phải phương pháp giải. Ví dụ chính tắc trong số là giải pháp của các phương trình tuyến tính liên quan đến cái gọi là "ma trận Hilbert":

Ma trận Hilbert

Ma trận là ví dụ điển hình của ma trận điều hòa : cố gắng giải một hệ thống với ma trận Hilbert lớn có thể trả về một giải pháp không chính xác.

Dưới đây là một Mathematica trình diễn: so sánh kết quả của số học chính xác

Table[LinearSolve[HilbertMatrix[n], HilbertMatrix[n].ConstantArray[1, n]], {n, 2, 12}]
{{1, 1}, {1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 
  1}, {1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1,
   1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 
  1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}

và số học không chính xác

Table[LinearSolve[N[HilbertMatrix[n]], N[HilbertMatrix[n].ConstantArray[1, n]]], {n, 2, 12}]
{{1., 1.}, {1., 1., 1.}, {1., 1., 1., 1.}, {1., 1., 1., 1., 1.},  
  {1., 1., 1., 1., 1., 1.}, {1., 1., 1., 1., 1., 1., 1.}, 
  {1., 1., 1., 1., 1., 1., 1., 1.}, {1., 1., 1., 1., 1., 1., 1., 1., 1.},  
  {1., 1., 1., 0.99997, 1.00014, 0.999618, 1.00062, 0.9994, 1.00031, 
  0.999931}, {1., 1., 0.999995, 1.00006, 0.999658, 1.00122, 0.997327, 
  1.00367, 0.996932, 1.00143, 0.999717}, {1., 1., 0.999986, 1.00022, 
  0.998241, 1.00831, 0.975462, 1.0466, 0.94311, 1.04312, 0.981529, 
  1.00342}}

(Nếu bạn đã dùng thử trong Mathematica , bạn sẽ lưu ý một vài thông báo lỗi cảnh báo về tình trạng điều hòa không khí xuất hiện.)

Trong cả hai trường hợp, chỉ cần tăng độ chính xác là không thể chữa khỏi; nó sẽ chỉ trì hoãn sự xói mòn không thể tránh khỏi của các số liệu.

Đây là những gì bạn có thể phải đối mặt với. Các giải pháp có thể khó khăn: lần đầu tiên, bạn quay lại bảng vẽ, hoặc lội qua các tạp chí / sách / bất cứ điều gì để tìm nếu ai đó đưa ra giải pháp tốt hơn bạn có; lần thứ hai, bạn có thể từ bỏ hoặc cải tổ vấn đề của mình thành một vấn đề dễ hiểu hơn.


Tôi sẽ để lại cho bạn một trích dẫn từ Dianne O'Leary:

Cuộc sống có thể ném cho chúng ta một số vấn đề không có điều kiện, nhưng không có lý do chính đáng để giải quyết cho một thuật toán không ổn định.


9

bởi vì 10 số thập phân cơ sở không thể được biểu thị trong cơ sở 2

hay nói cách khác 1/10 không thể chuyển thành phân số có lũy thừa bằng 2 trong mẫu số (về cơ bản là số dấu phẩy động)


11
Không hoàn toàn chính xác: 0,5 và 0,25 có thể được biểu thị trong cơ sở 2. Tôi nghĩ bạn có nghĩa là "không phải tất cả 10 số thập phân cơ sở".
Scott Whitlock

3
Chính xác hơn. Không phải tất cả các số phân số có thể được biểu diễn chính xác bằng cách sử dụng ký hiệu dấu phẩy động (nghĩa là với. Cả cơ sở 2 và cơ sở 10 đều có vấn đề chính xác này). Hãy thử và làm 9*3.3333333theo số thập phân và đồng ý với nó9*3 1/3
Martin York

1
Đây là nguồn phổ biến nhất của sự nhầm lẫn dấu phẩy động. .1 + .1 != .2bởi vì mã hóa nhị phân dấu phẩy động được sử dụng, không phải là số thập phân.
Sean McMillan

@SeanMcMillan: Và 1.0/3.0*3.0 != 1.0, bởi vì mã hóa nhị phân dấu phẩy động được sử dụng, không phải là nhị phân.
Keith Thompson

8

Trong toán học, có vô số số hữu tỉ. Một biến 32 bit chỉ có thể có 2 32 giá trị khác nhau và biến 64 bit chỉ có 2 giá trị 64 . Do đó, có vô số số hữu tỷ không có biểu diễn chính xác.

Chúng tôi có thể đưa ra các kế hoạch cho phép chúng tôi đại diện cho 1/3 một cách hoàn hảo, hoặc 1/100. Nó chỉ ra rằng cho nhiều mục đích thực tế, điều này không hữu ích. Có một ngoại lệ lớn: về tài chính, phân số thập phân thường xuất hiện. Điều đó chủ yếu là vì tài chính thực chất là một hoạt động của con người, không phải là hoạt động thể chất.

Do đó, chúng tôi thường chọn sử dụng dấu phẩy động nhị phân và làm tròn bất kỳ giá trị nào không thể được biểu diễn dưới dạng nhị phân. Nhưng trong tài chính, đôi khi chúng ta chọn dấu phẩy động thập phân và giá trị tròn cho giá trị thập phân gần nhất.


2
Thậm chí tệ hơn, trong khi một lượng bộ nhớ vô hạn (vô hạn) sẽ cho phép một người đại diện cho tất cả các lý trí, nó sẽ không đủ để đại diện cho thực tế. Thậm chí tệ hơn nữa, gần như tất cả các số thực không phải là số có thể tính toán được. Điều tốt nhất chúng ta có thể làm với một lượng bộ nhớ hữu hạn là xấp xỉ một tập hợp con phạm vi hữu hạn của các số thực.
David Hammen

4
@Kevin: Bạn đang nói về những con số có thể tính toán được, đó là một tập hợp con nhỏ (tập con có số đo bằng 0) của số thực.
David Hammen

1
+1 cho lời giải thích cơ bản nhất: Bạn đang cố gắng biểu diễn một số lượng vô hạn các số có số bit hữu hạn.
Raku

1
@DavidHammen: Các số tính toán là một tập hợp con nhỏ (số đo bằng 0) của số thực - nhưng mọi số bạn sẽ làm việc trong một chương trình, theo định nghĩa, có thể tính toán được.
Keith Thompson

3
@Giorgio: Nếu bạn chọn đại diện phù hợp , ví dụ căn bậc hai của 2 đại diện "√2". (Cũ HP-48 máy tính của tôi đã có thể làm chính xác điều đó, và bình phương giá trị mà kết quả chính xác 2.0.) Chỉ có một vô đếm được các số thực biểu diễn cho bất kỳ đại diện hữu hạn - nhưng không có tính toán có thể mang lại một số lượng đó không phải là, về nguyên tắc, đại diện. Trong thực tế, dấu phẩy động nhị phân giới hạn mạnh mẽ tập hợp các số có thể biểu diễn, với lợi ích của tốc độ nhanh và lưu trữ nhỏ so với các biểu tượng tượng trưng.
Keith Thompson

-2

"vấn đề làm tròn" thực sự rõ ràng duy nhất với các số dấu phẩy động mà tôi nghĩ là với các bộ lọc trung bình di chuyển:

$$ \ started {align} y [n] & = \ frac {1} {N} \ sum \ terms_ {i = 0} ^ {N-1} x [ni] \ & = y [n-1] + \ frac {1} {N} (x [n] - x [nN]) \ \ end {align} $$

để làm cho công việc này không bị tích tụ tiếng ồn, bạn muốn đảm bảo rằng $ x [n] $ bạn thêm vào trong các mẫu hiện tại giống hệt như $ x [nN] $ bạn sẽ trừ các mẫu $ N $ vào Tương lai. nếu không, thì điều khác biệt là một con rùa nhỏ bị mắc kẹt trong dòng trì hoãn của bạn và sẽ không bao giờ xuất hiện. đó là bởi vì bộ lọc trung bình di động này thực sự được chế tạo với IIR có cực ổn định biên ở mức $ z = 1 $ và số 0 hủy bỏ nó bên trong. nhưng, đó là một nhà tích hợp và bất kỳ crap nào được tích hợp và không bị loại bỏ hoàn toàn sẽ tồn tại trong tổng hợp tích hợp mãi mãi. đây là nơi mà điểm cố định không có vấn đề giống như số dấu phẩy động.


này, không phải $ LaTeX $ đánh dấu toán học hoạt động trong diễn đàn prog.SE ??? Điều đó thực sự khập khiễng nếu không.
robert bristow-johnson

1
Xem điều này trên meta.SO và các câu hỏi được liên kết
AakashM
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.