Không như một hằng số?


15

Tôi đã bắt gặp thành ngữ lập trình này gần đây:

const float Zero = 0.0;

mà sau đó được sử dụng trong so sánh:

if (x > Zero) {..}

Bất cứ ai có thể giải thích nếu điều này thực sự hiệu quả hơn hoặc có thể đọc hoặc duy trì hơn:

if (x > 0.0) {..}

LƯU Ý: Tôi có thể nghĩ ra các lý do khác để xác định hằng số này, tôi chỉ tự hỏi về việc sử dụng nó trong bối cảnh này .


31
Các nhà phát triển đang lên kế hoạch chuyển mã đến một vũ trụ nơi mà các định luật toán học khác nhau?
vaughandroid

6
Nghiêm túc mà nói, tôi không thể nghĩ ra một lý do chính đáng nào cho việc này. Những lời giải thích duy nhất tôi có thể đưa ra là các tiêu chuẩn mã hóa quá nhiệt tình, hoặc một số nhà phát triển đã nghe "số ma thuật là xấu" nhưng không hiểu tại sao (hoặc cái gì sẽ tạo thành một số ma thuật) ...
vaughandroid

@Baqueta -Một vũ trụ thay thế? Tôi nghĩ rằng họ đã sống ở đó! Đối với các số ma thuật, tôi đồng ý, tuy nhiên tôi sử dụng quy tắc ngón tay cái rằng Mọi thứ ngoại trừ 0 & 1 nên được thực hiện không đổi.
NWS

1
Nếu xcó loại float, sau đó x > 0.0buộc quảng cáo double, có thể kém hiệu quả hơn. Đó không phải là một lý do chính đáng cho việc sử dụng một tên liên tục tuy nhiên, chỉ dành riêng cho việc bảo đảm hằng của bạn có đúng loại (ví dụ 0f, float(0)hoặc decltype(x)(0)).
Mike Seymour

1
@JoSo: công bằng mà nói, loại 13.37không phải floatvậy double. Vì vậy, nếu bạn muốn floatthì có thể hiểu rằng gia sư của bạn đã đúng. Trong một số bối cảnh (ví dụ: gán cho float) 13.37sẽ được chuyển đổi hoàn toàn sang floatcái bạn muốn và trong các bối cảnh khác (ví dụ: khấu trừ kiểu mẫu), nó sẽ không static const floatbắt đầu như kiểu bạn dự định. Do đó, loại an toàn hơn. Tâm trí bạn, vì vậy sẽ được 13.37f! Tuy nhiên, có nhiều lý do khác để tránh macro hơn là "an toàn kiểu", do đó, rất có thể gia sư đã đưa ra một cuộc tranh luận tồi.
Steve Jessop

Câu trả lời:


29

Lý do có thể là bộ nhớ đệm, đặt tên hoặc loại cưỡng bức

Bộ nhớ đệm (không áp dụng)

Bạn muốn tránh chi phí tạo ra một đối tượng trong hành động so sánh. Trong Java một ví dụ sẽ là

BigDecimal zero = new BigDecimal ("0.0");

điều này bao gồm một quá trình tạo khá nặng và được phục vụ tốt hơn bằng cách sử dụng phương thức tĩnh được cung cấp:

BigDecimal zero = BigDecimal.ZERO;

Điều này cho phép so sánh mà không phải chịu chi phí tạo lặp đi lặp lại do BigDecimal được JVM lưu trữ trước trong quá trình khởi tạo.

Trong trường hợp của những gì bạn đã mô tả, một người nguyên thủy đang thực hiện cùng một công việc. Điều này phần lớn là dư thừa về bộ nhớ đệm và hiệu suất.

Đặt tên (không có khả năng)

Nhà phát triển ban đầu đang cố gắng cung cấp một quy ước đặt tên thống nhất cho các giá trị chung trong toàn hệ thống. Điều này có một số giá trị, đặc biệt là với các giá trị không phổ biến nhưng một cái gì đó cơ bản như số 0 chỉ có giá trị trong trường hợp bộ nhớ đệm trước đó.

Loại cưỡng bức (rất có thể)

Nhà phát triển ban đầu đang cố gắng ép buộc một loại nguyên thủy cụ thể để đảm bảo rằng các phép so sánh được chuyển thành loại chính xác của chúng và có thể theo một tỷ lệ cụ thể (số vị trí thập phân). Điều này là ổn, nhưng tên đơn giản "không" có lẽ không đủ chi tiết cho trường hợp sử dụng này với ZERO_1DP là cách diễn đạt ý định phù hợp hơn.


2
+1 cho loại cưỡng bức. Tôi sẽ thêm rằng trong các ngôn ngữ như C ++ cho phép quá tải toán tử, việc xác định hằng số và sử dụng typedefsẽ giữ loại biến thành chính xác một nơi và cho phép thay đổi nó mà không phải thay đổi mã.
Blrfl

3
Loại cưỡng bức rất có thể không phải là những gì họ đã cố gắng, tuy nhiên đây là lời giải thích tốt nhất về lý do tại sao nó có thể được thực hiện!
NWS

7
Đối buộc kiểu, tôi có thể thay chỉ cần sử dụng 0.0f.
Svish

Loại cưỡng bức đôi khi có thể hữu ích trong vb.net, trong đó việc thực hiện các toán tử bit trên byte mang lại kết quả byte. Nói byteVar1 = byteVar2 Or CB128có vẻ đẹp hơn một chút byteVar1 = byteVar2 Or CByte(128). Tất nhiên, có một hậu tố số thích hợp cho byte sẽ tốt hơn. Vì C # thúc đẩy các toán hạng của bitwise cho các toán tử intngay cả khi kết quả sẽ được đảm bảo phù hợp với một byte, nên vấn đề không liên quan ở đó.
supercat

Tôi không chắc chắn về việc có tên hằng là Zero cho '0' nhưng đôi khi nó giúp đọc được mã; ví dụ: có hằng số này bằng 0 - "ROOT_TYPE_ID = 0" sẽ giúp viết một câu lệnh như if (id! = ROOT_TYPE_ID) {..}
Tech Junkie

6

Đó là vì "Công cụ cắt ghép"

Một lý do có thể tôi không thấy được liệt kê ở đây là vì rất nhiều công cụ chất lượng đánh dấu việc sử dụng số ma thuật . Đó thường là một thực tế tồi khi có các số ma thuật được ném vào một thuật toán mà không làm cho chúng rõ ràng để thay đổi sau này, đặc biệt nếu chúng được sao chép ở nhiều vị trí trong mã.

Vì vậy, trong khi các công cụ này đúng về việc gắn cờ các vấn đề như vậy, chúng thường tạo ra các kết quả dương tính giả cho các tình huống trong đó các giá trị này vô hại và rất có thể là tĩnh hoặc chỉ là các giá trị khởi tạo.

Và khi điều đó xảy ra, đôi khi bạn phải đối mặt với sự lựa chọn:

  • đánh dấu chúng là dương tính giả, nếu công cụ cho phép nó (thường với một nhận xét được định dạng đặc biệt, gây khó chịu cho những người KHÔNG sử dụng công cụ)
  • hoặc trích xuất các giá trị này cho hằng số, cho dù nó có quan trọng hay không.

Về hiệu suất

Nó phụ thuộc vào ngôn ngữ tôi đoán, nhưng điều này khá phổ biến trong Java và không có tác động hiệu năng, vì các giá trị được nội tuyến tại thời gian biên dịch nếu chúng là hằng số thực static final. Nó sẽ không có tác động trong C hoặc C ++ nếu chúng được khai báo là hằng số hoặc thậm chí là macro tiền xử lý.


5

Điều này có thể có ý nghĩa vì nó xác định rõ ràng Zerolà loại float.

Ít nhất trong C và C ++, giá trị 0.0là loại double, trong khi tương đương float0.0f. Vì vậy, giả sử xbạn so sánh với luôn luôn là một floatcâu nói

x > 0.0

trong khi thực sự thúc đẩy xđể doublephù hợp với loại 0.0có thể dẫn đến các vấn đề (đặc biệt là với các bài kiểm tra bình đẳng). Việc so sánh mà không chuyển đổi tất nhiên sẽ là

x > 0.0f

mà giống như

float Zero = 0.0; // double 0.0 converted to float  
x > Zero

Tuy nhiên, tôi nghĩ sẽ hữu ích hơn nhiều khi kích hoạt các cảnh báo về chuyển đổi trong trình biên dịch thay vì người dùng viết mã khó xử.


1

Trước hết, ở đây số không được định nghĩa là float, không int. Tất nhiên, điều này không ảnh hưởng đến bất cứ điều gì trong so sánh, nhưng trong các trường hợp khác khi sử dụng hằng số này, nó có thể tạo ra sự khác biệt.

Tôi thấy không có lý do khác tại sao Zerođược tuyên bố là một hằng số ở đây. Đó chỉ là một số phong cách mã hóa, và tốt hơn là nên theo phong cách này nếu nó được sử dụng ở mọi nơi khác trong chương trình nhất định đó.


1

Nó gần như chắc chắn chính xác như hiệu quả trong khi thực hiện (trừ khi trình biên dịch của bạn rất nguyên thủy) và rất ít hiệu quả trong quá trình biên dịch.

Về việc liệu điều đó có dễ đọc hơn x > 0... hãy nhớ rằng có những người thành thật, thực sự, nghĩ rằng COBOL là một ý tưởng tuyệt vời và rất vui khi làm việc với - và sau đó có những người nghĩ giống hệt về C. (Rumor có thậm chí còn tồn tại một số lập trình viên có cùng quan điểm về C ++!) Nói cách khác, bạn sẽ không có được thỏa thuận chung về điểm này và có lẽ không đáng để tranh cãi.


0

[là] đây thực sự là bất kỳ hiệu quả hơn hoặc có thể đọc hoặc duy trì hơn:

if (x > 0.0) {..}

Nếu bạn đang viết mã chung (tức là không phải loại cụ thể), thì rất có thể. Một zero()hàm có thể áp dụng cho bất kỳ loại đại số nào, hoặc bất kỳ loại nào là bổ sung wrt nhóm. Nó có thể là một số nguyên, nó có thể là một giá trị dấu phẩy động, thậm chí nó có thể là một hàm nếu biến của bạn là một hàm trong một không gian tuyến tính (ví dụ x là một hàm tuyến tính có dạng z -> a_x * z + b_x) và sau đó zero()cung cấp hàm với cả a và b đều zero()thuộc kiểu cơ bản.

Vì vậy, bạn sẽ mong đợi mã như vậy, giả sử, C ++ có thể (mặc dù một zero()AFAIK không phổ biến lắm) hoặc ở Julia và có thể các ngôn ngữ khác.

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.