Mã chuyển đổi một giá trị thành một đại diện khác, sau đó chuyển đổi nó trở lại nơi nó bắt đầu là xấu, nhưng làm thế nào? [đóng cửa]


35

Tôi đã đọc một bài viết về thực hành lập trình xấu .

Nó đã đề cập -

"Mã Yo-Yo" chuyển đổi một giá trị thành một biểu diễn khác, sau đó chuyển đổi nó trở lại nơi bắt đầu (ví dụ: chuyển đổi một số thập phân thành một chuỗi và sau đó trở lại thành một số thập phân hoặc đệm một chuỗi và sau đó cắt xén nó)

Tôi không hiểu tại sao ví dụ cụ thể mà anh ấy đưa ra là một cách tồi để viết chương trình. Tôi có vẻ ổn khi chuyển đổi trở lại nếu tình huống yêu cầu để giá trị có thể được sử dụng.

Bất cứ ai có thể giải thích thêm về điều này?


4
đề nghị đọc: Thảo luận về $ {blog}
gnat

8
Hầu hết thời gian nó chỉ là dư thừa và nó chỉ xảy ra vì lập trình viên không biết cách nào tốt hơn để có được thứ họ muốn. Mục blog đưa ra một ví dụ điển hình một vài đoạn sau : "Roundabout code" that accomplishes in many instructions what could be done with far fewer (eg: rounding a number by converting a decimal into a formatted string, then converting the string back into a decimal). if the situation is so that they have to be used?- tình huống đó sẽ là gì?
Konrad Morawski

3
@gnat Tôi không hiểu làm thế nào mà điều này trở thành một câu hỏi tồi. Nếu bạn muốn tôi có thể chỉnh sửa nó để nói "là mã chuyển đổi và chuyển đổi lại một giá trị xấu?" và nó sẽ không phù hợp với mẫu đó nữa.
djechlin

5
Gần đây tôi đã tìm thấy mã trong Java lặp lại qua một mảng, tuần tự hóa từng đối tượng thành một đối tượng JSON, sử dụng nối chuỗi, không phải là trình tuần tự hóa JSON. Kết quả sau đó được chuyển đến một phương thức riêng, phân tích cú pháp mảng JSON để trích xuất một loạt ID, sau đó chuyển ID ở một nơi khác. Đây là cách sử dụng duy nhất của mảng JSON đó trong hệ thống. Đó là mã yo-yo. Không có lý do để chuyển đổi qua lại. Chúng ta có thể đơn giản chuyển ID từ các đối tượng ban đầu.
Brandon

3
decimal myValue = decimal.Parse(dataReader["myColumn"].ToString())là một tiểu thú cưng của tôi.
Matthew

Câu trả lời:


125

Thậm chí nếu bạn làm cần cả số và chuỗi đại diện của một số, nó tốt hơn để chuyển đổi chỉ một lần và cũng treo trên giá trị ban đầu, thay vì chuyển đổi một lần nữa mỗi khi bạn cần một hay khác.

Nguyên tắc là, như mọi khi, mã không tồn tại không thể có khiếm khuyết tinh vi , trong khi mã tồn tại thường có. Điều đó nghe có vẻ hoang tưởng, nhưng kinh nghiệm dạy chúng ta rằng nó phù hợp. Nếu bạn tiếp cận lập trình với nỗi lo lắng thường trực "Tôi không thực sự đủ thông minh để hiểu hệ thống phức tạp này", bạn đang đi đúng hướng.


5
Nói hay lắm. Tất cả chúng ta nên lập trình viên nên thận trọng.
Neil

58
"Mã không tồn tại không thể có khiếm khuyết tinh vi, trong khi mã thường tồn tại" ước gì tôi có thể +2 bạn cho điều đó. Đừng bao giờ đánh giá thấp giá trị của việc không phải viết mã.
Benjamin Gruenbaum

2
Nhưng thực hiện một vài thao tác đơn giản (chuyển đổi thành chuỗi và trở lại) có thể ít phức tạp hơn (dễ hiểu và mã hơn) so với cách thao tác "đúng" của các bit. Và giữ tất cả dữ liệu của một danh mục trong một hình thức duy nhất thường là một ý tưởng tốt, ngay cả khi dữ liệu nhất định sẽ chắc chắn được chuyển đổi sang các hình thức khác.
Daniel R Hicks

36
@DanielRHicks vì vậy hãy chuyển đổi ngày đơn giản đó (10 tháng 11 năm 2014) thành một chuỗi, -> 10-11-2014 và quay lại một ngày -> (11 tháng 10 năm 2014) chờ gì?
Pieter B

20
@PieterB Có một phần mềm kế toán lớn của Đức không hoạt động trên các máy tính có ngôn ngữ không phải của Đức vì nó làm việc này. Đầu tiên, nó chuyển đổi ngày thành chuỗi bằng ngôn ngữ hệ thống và sau đó cố gắng phân tích nó với một ngôn ngữ cố định và phàn nàn về định dạng bất hợp pháp. Nó cũng làm như vậy với các số và các dấu phân cách thập phân khác nhau, ngoại trừ việc nó không phàn nàn ở đó, nó làm hỏng dữ liệu và thể hiện hành vi kỳ lạ. Mất nhiều ngày để tìm ra điều đó.
CodeInChaos

23

Thật tệ vì ba lý do chính:

  1. Nó cho thấy bạn chưa nghĩ đến loại / định dạng thực sự nên là gì nhưng thay vào đó chuyển đổi nó thành thứ bạn cần tại thời điểm đó. Điều này cho thấy thiếu suy nghĩ thiết kế.
  2. Nó có thể lãng phí. Bạn gần như chắc chắn lãng phí chu kỳ và dòng mã, thực hiện các chuyển đổi không cần phải ở đó. Điều này sẽ làm cho mã của bạn chậm hơn và cồng kềnh hơn mức cần thiết.
  3. Chuyển đổi loại dễ bị lỗi tinh tế. Bằng cách chấm điểm các chuyển đổi này thông qua mã của bạn, bạn sẽ tăng khả năng xảy ra lỗi.

Tôi nghi ngờ lý do 1 là lý do mà nguồn của bạn đã nghĩ đến dựa trên bối cảnh mà nó được đề cập.


6

Tôi sẽ viết lại mô tả là "mã chuyển đổi một loại thành một đại diện khác với mục đích làm một việc gì đó có thể được thực hiện tốt hoặc tốt hơn trong bản gốc và sau đó chuyển đổi nó trở lại. Có nhiều tình huống chuyển đổi một cái gì đó thành một loại khác nhau, hành động theo nó và chuyển đổi nó trở lại là hoàn toàn phù hợp và không làm như vậy sẽ dẫn đến hành vi không chính xác.

Ví dụ: chuyển đổi là tốt:
Một có bốn floatgiá trị của các dấu hiệu tùy ý có cường độ có thể khác nhau theo hệ số lên tới 1.000 và người ta cần tính tổng trong khoảng 0,625 đơn vị ở vị trí cuối cùng. Chuyển đổi tất cả bốn giá trị sang double, tính toán tổng và chuyển đổi kết quả trở lại floatsẽ hiệu quả hơn nhiều so với bất kỳ cách tiếp cận nào floatchỉ sử dụng một mình.
Các giá trị dấu phẩy động có độ chính xác cao nhất đến 0,5 đơn vị ở vị trí cuối cùng (ULP). Ví dụ này sẽ yêu cầu rằng lỗi làm tròn trường hợp xấu nhất không quá 25% so với lỗi trường hợp xấu nhất tối ưu. Sử dụng gấp đôi sẽ mang lại một giá trị sẽ chính xác trong 0,5001 ULP. Trong khi yêu cầu 0,625 ULP có vẻ bị hạn chế, các yêu cầu như vậy thường rất quan trọng trong các thuật toán xấp xỉ liên tiếp. Các ràng buộc lỗi càng chặt chẽ được chỉ định, yêu cầu lặp lại trong trường hợp xấu nhất càng thấp.

Như một ví dụ khi chuyển đổi là xấu:
Một người có số dấu phẩy động và muốn xuất ra một chuỗi sẽ biểu thị giá trị của nó một cách duy nhất. Một cách tiếp cận là chuyển đổi số thành một chuỗi với một số chữ số nhất định, thử chuyển đổi lại và xem kết quả có khớp hay không.

Nhưng đây thực sự là một cách tiếp cận kém. Nếu một chuỗi thập phân biểu thị một giá trị nằm gần như chính xác ở điểm giữa của hai giá trị dấu phẩy động, thì phương pháp chuỗi nổi sẽ khá tốn kém để đảm bảo rằng nó sẽ luôn mang lại floatgiá trị gần hơn và nhiều phương thức chuyển đổi như vậy không sẽ không bảo đảm như vậy (trong số những điều khác, làm như vậy trong một số trường hợp yêu cầu đọc tất cả các chữ số của một số, ngay cả khi nó dài hàng tỷ chữ số).

Nó rẻ hơn nhiều đối với một phương thức để đảm bảo rằng nó sẽ luôn trả về một giá trị nằm trong 0,5625 đơn vị ở vị trí cuối cùng (ULP) của giá trị được biểu diễn. Một thói quen định dạng thập phân "có thể đảo ngược" mạnh mẽ sẽ tính toán khoảng cách giá trị đầu ra từ giá trị chính xác và tiếp tục xuất các chữ số cho đến khi kết quả nằm trong 0,375 (ULP) nếu không phải là 0,25 (ULP). Mặt khác, nó có thể xuất ra một chuỗi mà một số phương thức chuyển đổi sẽ xử lý chính xác, nhưng các phương thức chuyển đổi khác sẽ không.

Tốt hơn là đôi khi xuất ra một chữ số có thể không "cần thiết" hơn đầu ra một giá trị có thể bị hiểu sai. Phần quan trọng là quyết định có bao nhiêu chữ số nên được đưa ra dựa trên các tính toán số liên quan đến quá trình đầu ra, thay vì kết quả của một phương pháp cụ thể để chuyển chuỗi trở lại thành một số.


1
Ví dụ của bạn không trả về giá trị ban đầu, đó là những gì OP đang hỏi về. Nó chỉ trả về một giá trị với cùng loại, được tính từ nhiều đầu vào.
CJ Dennis

2

Nhiều lý do

  1. Điều đó là vô nghĩa và làm tăng thêm sự phức tạp - cả về số lượng mã để viết và duy trì cũng như lượng thời gian CPU cần thiết

    1. Nó có thể mất độ chính xác hoặc tệ hơn, làm hỏng hoàn toàn giá trị

    2. Nó lãng phí bộ nhớ (có khả năng, tùy thuộc vào ngôn ngữ) khi bạn kết thúc việc lưu trữ nhiều đại diện hơn cho một số bạn cần

Một thực hành tốt là chỉ giữ biểu diễn đầu tiên, chính xác nhất có thể, cho bất kỳ dữ liệu nào bạn nhận được. Thực hiện bất kỳ tính toán nào bằng dữ liệu này và chỉ bao giờ chuyển đổi nó nếu bạn cần xuất dữ liệu hoặc hiển thị nó ở định dạng dễ đọc hơn.


điều này dường như không thêm bất cứ điều gì đáng kể vào các điểm được thực hiện và giải thích trong các câu trả lời trước
gnat

2
Điều đó biện minh cho một cuộc bỏ phiếu xuống? Tôi tin rằng bài viết của tôi có khả năng ngắn gọn hơn
Câu chuyện Jon

cả hai câu trả lời trước đây thực sự có vẻ ngắn gọn hơn đối với tôi, cả hai
gnat

0

Tại sao? Bởi vì ngay cả những người giỏi nhất trong chúng ta cũng có thể mắc sai lầm.

Hãy xem điều gì đã xảy ra khi Microsoft cố gắng thực hiện định dạng "khứ hồi" một cách cụ thể để đảm bảo chuyển đổi chuỗi <-> float an toàn: https://stackoverflow.com/q/24299692/541686


0

Khi tôi ở trường (và trường bưu điện về kỹ thuật điện), chúng tôi được dạy cách chia sau khi nhân. Phân chia thường nhiều chữ số và được làm tròn. Nhân sau khi chia nhân với lỗi chia.

Chuyển đổi loại là như nhau, bạn có nguy cơ mất dữ liệu. CInt (1.3) = 1.

Theo ngôn ngữ của tôi, Basic, chúng tôi chỉ thực hiện chuyển đổi loại (một chương trình VB6 dành 90% thời gian để thực hiện chuyển đổi ANSI / Unicode, cho tất cả các lệnh gọi API thực hiện trong thời gian chạy).

Chuyển đổi loại được ngụ ý trong tất cả chúng ta làm.

 Print 5

Chuỗi "5" được in từ chữ số.

form1.caption = "My Form"

Chuỗi ký tự unicode được chuyển đổi thành chuỗi ANSI và được gửi đến SetWindowsTextA bằng gói biểu mẫu.

Ngay cả điều này hoạt động trong cơ bản

a = "5"
b = 3

c = a + b (= 8)

Tôi là một lập trình viên biến thể ngày nay - tôi thậm chí không nghĩ về loại. Tôi chỉ dựa vào sự tự động.

Dù sao 3 con thú cưng của tôi là

Gán chuỗi ký tự cho các biến để sử dụng chúng (lãng phí bộ nhớ và chậm)

Các hàm vô nghĩa khi mã có thể là nội tuyến (và trình biên dịch có thể sẽ hoàn tác chức năng của bạn và nội tuyến nó bằng mọi cách)

Đặt tất cả các đối tượng thành không có gì là dòng cuối cùng trước Hàm kết thúc hoặc kết thúc chương trình.

và thứ 4 cho các chương trình ngắn

Làm mờ vô số 3 biến của bạn trong chương trình 5 dòng.

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.