Tại sao C không có phao không dấu?


131

Tôi biết, câu hỏi dường như là lạ. Lập trình viên đôi khi nghĩ quá nhiều. Vui lòng đọc tiếp ...

Trong CI sử dụng signedunsignedsố nguyên rất nhiều. Tôi thích thực tế là trình biên dịch cảnh báo tôi nếu tôi làm những việc như gán một số nguyên đã ký cho một biến không dấu. Tôi nhận được cảnh báo nếu tôi so sánh đã ký với số nguyên không dấu và nhiều hơn nữa.

Tôi thích những cảnh báo này. Họ giúp tôi giữ mã chính xác.

Tại sao chúng ta không có sự sang trọng giống nhau cho phao? Một căn bậc hai chắc chắn sẽ không bao giờ trả về một số âm. Cũng có những nơi khác mà giá trị float âm không có ý nghĩa. Ứng cử viên hoàn hảo cho một float không dấu.

Btw - Tôi không thực sự quan tâm đến một chút chính xác mà tôi có thể nhận được bằng cách loại bỏ bit dấu hiệu khỏi phao. Tôi siêu hạnh phúc với floats như họ bây giờ. Đôi khi tôi chỉ muốn đánh dấu một dấu phẩy là không dấu và nhận được cùng một loại cảnh báo mà tôi nhận được với các số nguyên.

Tôi không biết về bất kỳ ngôn ngữ lập trình nào hỗ trợ các số dấu phẩy động không dấu.

Bất cứ ý tưởng tại sao họ không tồn tại?


BIÊN TẬP:

Tôi biết rằng x87 FPU không có hướng dẫn để xử lý các số float không dấu. Cho phép chỉ sử dụng các hướng dẫn nổi đã ký. Việc sử dụng sai (ví dụ: xuống dưới 0) có thể được coi là hành vi không xác định theo cách tương tự như tràn các số nguyên đã ký không được xác định.


4
Thật thú vị, bạn có thể đăng một ví dụ về một trường hợp mà việc đánh máy chữ ký là hữu ích?

litb, nhận xét của bạn hướng vào tôi? nếu vậy, tôi không hiểu được

Iraimbilanja yeah :) fabs không thể trả về số âm, bởi vì nó trả về giá trị tuyệt đối của đối số của nó
Johannes Schaub - litb

Right.i đã không hỏi làm thế nào một unsignfloat giả định có thể giúp xác chết. Tôi đã hỏi là gì: trong tình huống nào pipenbrinck tìm thấy chữ ký Int đánh dấu hữu ích (dẫn anh ta đến với cơ chế tương tự cho phao). liên quan đến an toàn về

1
Có một tối ưu hóa vi mô không dấu cho kiểm tra trong phạm vi điểm: ((không dấu) (p-min)) <(tối đa), chỉ có một nhánh, nhưng, như mọi khi, tốt nhất là lập hồ sơ để xem nếu nó thực sự hữu ích (tôi chủ yếu sử dụng nó trên 386 lõi vì vậy tôi không biết CPU hiện đại đối phó như thế nào).
Skizz

Câu trả lời:


114

Tại sao C ++ không hỗ trợ cho các float không dấu là do không có hoạt động mã máy tương đương để CPU thực thi. Vì vậy, nó sẽ rất không hiệu quả để hỗ trợ nó.

Nếu C ++ đã hỗ trợ nó, thì đôi khi bạn sẽ sử dụng một float không dấu và không nhận ra rằng hiệu suất của bạn vừa bị giết. Nếu C ++ hỗ trợ thì mọi thao tác dấu phẩy động sẽ cần được kiểm tra để xem nó có được ký hay không. Và đối với các chương trình thực hiện hàng triệu thao tác dấu phẩy động, điều này không được chấp nhận.

Vì vậy, câu hỏi sẽ là tại sao những người triển khai phần cứng không hỗ trợ nó. Và tôi nghĩ rằng câu trả lời cho điều đó là không có tiêu chuẩn float không dấu được xác định ban đầu. Vì các ngôn ngữ muốn tương thích ngược, ngay cả khi ngôn ngữ được thêm vào, không thể sử dụng ngôn ngữ đó. Để xem thông số điểm nổi, bạn nên xem Điểm nổi 754 tiêu chuẩn của IEEE .

Bạn có thể tránh được việc không có loại dấu phẩy động không dấu mặc dù bằng cách tạo một lớp float không dấu, đóng gói một số float hoặc double và đưa ra các cảnh báo nếu bạn cố gắng chuyển số âm. Điều này kém hiệu quả hơn, nhưng có lẽ nếu bạn không sử dụng chúng mạnh mẽ, bạn sẽ không quan tâm đến việc giảm hiệu suất nhẹ.

Tôi chắc chắn thấy sự hữu ích của việc có một dấu phẩy không dấu. Nhưng C / C ++ có xu hướng chọn hiệu quả hoạt động tốt nhất cho mọi người vì sự an toàn.


17
C / C ++ không yêu cầu các thao tác mã máy cụ thể để thực hiện ngôn ngữ. Trình biên dịch C / C ++ sớm có thể tạo mã dấu phẩy động cho 386 - CPU không có FPU! Trình biên dịch sẽ tạo các lệnh gọi thư viện để mô phỏng các hướng dẫn của FPU. Do đó, một ufloat có thể được thực hiện mà không cần hỗ trợ CPU
Skizz

10
Skizz, trong khi đó là chính xác, Brian đã giải quyết điều này - rằng vì không có mã máy tương đương, hiệu suất sẽ rất tệ khi so sánh.
Anthony

2
@Brian R. Bondy: Tôi đã mất bạn ở đây: "bởi vì không có hoạt động mã máy tương đương để CPU thực thi ...". Bạn có thể vui lòng giải thích, trong điều kiện đơn giản hơn?
Lazer

2
Lý do OP muốn hỗ trợ cho các float không dấu là cho các thông báo cảnh báo, vì vậy thực sự nó không liên quan gì đến giai đoạn tạo mã của trình biên dịch - chỉ liên quan đến cách kiểm tra kiểu trước đó - vì vậy hỗ trợ cho chúng trong mã máy là không liên quan và (như đã được thêm vào cuối câu hỏi) các hướng dẫn dấu phẩy động thông thường có thể được sử dụng để thực hiện thực tế.
Joe F

2
Tôi không chắc chắn tôi thấy tại sao điều này sẽ ảnh hưởng đến hiệu suất. Giống như với int, tất cả các kiểm tra loại liên quan đến dấu hiệu có thể xảy ra tại thời điểm biên dịch. OP gợi ý rằng unsigned floatsẽ được triển khai như thường lệ floatvới kiểm tra thời gian biên dịch để đảm bảo rằng các hoạt động không có ý nghĩa nhất định không bao giờ được thực hiện. Mã máy và hiệu suất có thể giống hệt nhau, bất kể số float của bạn có được ký hay không.
xanderflood

14

Có một sự khác biệt đáng kể giữa các số nguyên có dấu và không dấu trong C / C ++:

value >> shift

các giá trị đã ký giữ cho bit trên cùng không thay đổi (dấu mở rộng), các giá trị không dấu xóa bit trên cùng.

Lý do không có dấu phẩy không dấu là bạn nhanh chóng gặp phải tất cả các loại vấn đề nếu không có giá trị âm. Xem xét điều này:

float a = 2.0f, b = 10.0f, c;
c = a - b;

C có giá trị gì? -số 8. Nhưng điều đó có nghĩa là gì trong một hệ thống không có số âm. FLOAT_MAX - 8 có lẽ? Trên thực tế, điều đó không hoạt động vì FLOAT_MAX - 8 là FLOAT_MAX do hiệu ứng chính xác nên mọi thứ thậm chí còn khó xử hơn. Điều gì xảy ra nếu nó là một phần của biểu thức phức tạp hơn:

float a = 2.0f, b = 10.0f, c = 20.0f, d = 3.14159f, e;
e = (a - b) / d + c;

Đây không phải là vấn đề đối với số nguyên do bản chất của hệ thống bổ sung của 2.

Cũng xem xét các hàm toán học tiêu chuẩn: sin, cos và tan sẽ chỉ hoạt động với một nửa giá trị đầu vào của chúng, bạn không thể tìm thấy nhật ký của các giá trị <1, bạn không thể giải phương trình bậc hai: x = (-b +/- root ( bb - 4.ac)) / 2.a, v.v. Trên thực tế, nó có thể sẽ không hoạt động đối với bất kỳ hàm phức tạp nào vì chúng có xu hướng được thực hiện dưới dạng xấp xỉ đa thức sẽ sử dụng các giá trị âm ở đâu đó.

Vì vậy, phao không dấu là khá vô dụng.

Nhưng điều đó không có nghĩa là một lớp kiểm tra các giá trị float không hữu ích, bạn có thể muốn kẹp các giá trị vào một phạm vi nhất định, ví dụ như tính toán RGB.


@Skizz: nếu đại diện là một vấn đề, ý bạn là nếu ai đó có thể nghĩ ra một phương pháp để lưu trữ phao hiệu quả như vậy 2's complement, sẽ không có vấn đề gì với việc có phao không dấu?
Lazer

3
value >> shift for signed values leave the top bit unchanged (sign extend) Bạn có chắc chắn về điều đó không? Tôi nghĩ rằng đó là hành vi được xác định thực hiện, ít nhất là đối với các giá trị được ký âm.
Dan

@Dan: Chỉ cần nhìn vào tiêu chuẩn gần đây và thực sự nói rằng đó là việc triển khai được xác định - Tôi đoán đó chỉ là trong trường hợp CPU không có sự thay đổi đúng với hướng dẫn mở rộng dấu hiệu.
Skizz


1
điểm nổi truyền thống bão hòa (đến - / + Inf) thay vì gói. Bạn có thể mong đợi phép trừ tràn không dấu sẽ bão hòa 0.0, hoặc có thể là Inf hoặc NaN. Hoặc chỉ là Hành vi không xác định, như OP đề xuất trong phần chỉnh sửa cho câu hỏi. Re: trig function: vì vậy không xác định các phiên bản đầu vào không dấu sinvà vv, và đảm bảo coi giá trị trả về của chúng là đã ký. Câu hỏi không đề xuất thay thế float bằng float không dấu, chỉ cần thêm unsigned floatdưới dạng một kiểu mới.
Peter Cordes

9

(Như một bên, Perl 6 cho phép bạn viết

subset Nonnegative::Float of Float where { $_ >= 0 };

và sau đó bạn có thể sử dụng Nonnegative::Floatgiống như bất kỳ loại nào khác.)

Không có hỗ trợ phần cứng cho các hoạt động dấu phẩy động không dấu, vì vậy C không cung cấp nó. C hầu hết được thiết kế để trở thành "lắp ráp di động", nghĩa là gần với kim loại nhất có thể mà không bị ràng buộc với một nền tảng cụ thể.

[biên tập]

C giống như lắp ráp: những gì bạn thấy là chính xác những gì bạn nhận được. Một ẩn ý "Tôi sẽ kiểm tra xem phao này là không âm đối với bạn" đi ngược lại triết lý thiết kế của nó. Nếu bạn thực sự muốn nó, bạn có thể thêm assert(x >= 0)hoặc tương tự, nhưng bạn phải làm điều đó một cách rõ ràng.


svn.perl.org/parrot/trunk/lacular/perl6/docs/STATUS nói có, nhưng of ...không phân tích cú pháp.
ephemient

8

Tôi tin rằng int unsign đã được tạo vì nhu cầu về giá trị biên lớn hơn so với int đã ký có thể cung cấp.

Một chiếc phao có lề lớn hơn nhiều, vì vậy không bao giờ có nhu cầu 'vật lý' cho một chiếc phao không dấu. Và khi bạn chỉ ra chính mình trong câu hỏi của bạn, độ chính xác 1 bit bổ sung là không có gì để giết.

Chỉnh sửa: Sau khi đọc câu trả lời của Brian R. Bondy , tôi phải sửa đổi câu trả lời của mình: Anh ấy chắc chắn đúng rằng các CPU bên dưới không có các hoạt động thả nổi không dấu. Tuy nhiên, tôi vẫn giữ niềm tin rằng đây là một quyết định thiết kế dựa trên những lý do tôi đã nêu ở trên ;-)


2
Ngoài ra, phép cộng và phép trừ các số nguyên là cùng dấu hoặc không dấu - dấu phẩy động, không quá nhiều. Ai sẽ làm thêm công việc để hỗ trợ cả số float đã ký và chưa ký với tiện ích cận biên tương đối thấp của tính năng như vậy?
ephemient

7

Tôi nghĩ Treb đang đi đúng hướng. Điều quan trọng hơn đối với các số nguyên mà bạn có loại không dấu tương ứng. Đó là những cái được sử dụng trong dịch chuyển bit và được sử dụng trong bản đồ bit . Một chút dấu hiệu chỉ được đưa vào đường. Ví dụ, dịch chuyển sang phải một giá trị âm, giá trị kết quả được triển khai được xác định trong C ++. Làm điều đó với một số nguyên không dấu hoặc tràn như vậy đã xác định hoàn hảo ngữ nghĩa bởi vì không có bit nào như vậy.

Vì vậy, đối với các số nguyên ít nhất, nhu cầu về một loại không dấu riêng biệt mạnh hơn là chỉ đưa ra các cảnh báo. Tất cả các điểm trên không cần phải được xem xét cho phao. Vì vậy, theo tôi, không có nhu cầu thực sự hỗ trợ phần cứng cho họ và C sẽ không hỗ trợ họ vào thời điểm đó.


5

Một căn bậc hai chắc chắn sẽ không bao giờ trả về một số âm. Cũng có những nơi khác mà giá trị float âm không có ý nghĩa. Ứng cử viên hoàn hảo cho một float không dấu.

C99 hỗ trợ các số phức và một dạng chung của sqrt, do đó sqrt( 1.0 * I)sẽ là số âm.


Các nhà bình luận đã nêu bật một chút bóng ở trên, trong đó tôi đã đề cập đến sqrtmacro chung loại chứ không phải là hàm và nó sẽ trả về giá trị dấu phẩy động vô hướng bằng cách cắt phức tạp thành thành phần thực của nó:

#include <complex.h>
#include <tgmath.h>

int main () 
{
    complex double a = 1.0 + 1.0 * I;

    double f = sqrt(a);

    return 0;
}

Nó cũng chứa một rắm não, vì phần thực của sqrt của bất kỳ số phức nào là dương hoặc bằng 0 và sqrt (1.0 * I) là sqrt (0.5) + sqrt (0.5) * Tôi không -1.0.


Có, nhưng bạn gọi một hàm có tên khác nếu bạn làm việc với các số phức. Ngoài ra các loại trả lại là khác nhau. Điểm tốt mặc dù!
Nils Pipenbrinck

4
Kết quả của sqrt (i) là một số phức. Và vì các số phức không được đặt hàng, bạn không thể nói một số phức là negativ (tức là <0)
quinmars

1
quinmars, chắc chắn đó không phải là csqrt? hoặc bạn nói về toán học thay vì C? Dù sao thì tôi cũng đồng ý rằng đó là một điểm tốt :)
Johannes Schaub - litb

Thật vậy, tôi đã nói về toán học. Tôi chưa bao giờ xử lý các số phức trong c.
quinmars

1
"căn bậc hai chắc chắn sẽ không bao giờ trả về số âm." -> sqrt(-0.0)thường sản xuất -0.0. Tất nhiên -0.0 không phải là giá trị âm .
chux - Tái lập Monica

4

Tôi đoán nó phụ thuộc vào việc các thông số kỹ thuật của dấu phẩy động chỉ được ký và hầu hết các ngôn ngữ lập trình đều sử dụng chúng.

Bài viết trên Wikipedia về các số dấu phẩy động của IEEE-754

Chỉnh sửa: Ngoài ra, như được lưu ý bởi những người khác, hầu hết các phần cứng không hỗ trợ các phao không âm, do đó, các loại phao thông thường sẽ hiệu quả hơn vì có hỗ trợ phần cứng.


C đã được giới thiệu từ lâu trước khi tiêu chuẩn IEEE-754 xuất hiện
phuclv

@phuclv Không phải là phần cứng dấu phẩy động phổ biến. Nó đã được áp dụng vào tiêu chuẩn C "một vài" năm sau đó. Có lẽ có một số tài liệu nổi trên internet về nó. (Ngoài ra, bài viết trên wikipedia có đề cập đến C99).
Tobias Wärre

Tôi không hiểu ý của bạn. Không có "phần cứng" trong câu trả lời của bạn và IEEE-754 được sinh ra sau C, vì vậy các loại dấu phẩy động trong C không thể phụ thuộc vào tiêu chuẩn IEEE-754, trừ khi các loại đó được đưa vào C muộn hơn nhiều
phuclv

@phuclv C là / còn được gọi là lắp ráp di động, vì vậy nó có thể khá gần với phần cứng. Ngôn ngữ đạt được các tính năng trong nhiều năm, ngay cả khi (trước thời của tôi) float được triển khai trong C, nó có thể là một hoạt động dựa trên phần mềm và khá tốn kém. Tại thời điểm trả lời câu hỏi này, rõ ràng tôi đã nắm bắt tốt hơn những gì tôi đang cố gắng giải thích hơn bây giờ. Và nếu bạn nhìn vào câu trả lời được chấp nhận, bạn có thể hiểu tại sao tôi lại đề cập đến tiêu chuẩn IEE754. Điều tôi không hiểu là bạn đã đánh lừa câu trả lời 10 năm không phải là câu trả lời được chấp nhận?
Tobias Wärre

3

Tôi nghĩ lý do chính là các float không dấu sẽ thực sự hạn chế sử dụng so với ints không dấu. Tôi không mua lập luận rằng đó là vì phần cứng không hỗ trợ nó. Các bộ xử lý cũ hơn hoàn toàn không có khả năng dấu phẩy động, tất cả đều được mô phỏng trong phần mềm. Nếu phao không dấu là hữu ích, trước tiên chúng sẽ được triển khai trong phần mềm và phần cứng sẽ theo sau.


4
Nền tảng đầu tiên của PDP-7, C, có một đơn vị điểm nổi phần cứng tùy chọn. Nền tảng tiếp theo của PDP-11, C, có phần nổi 32 bit. 80x86 đến một thế hệ sau, với một số công nghệ là một thế hệ đằng sau.
ephemient

3

Các kiểu số nguyên không dấu trong C được định nghĩa theo cách tuân theo các quy tắc của vòng đại số trừu tượng. Ví dụ: đối với bất kỳ giá trị X và Y nào, việc thêm XY vào Y sẽ mang lại X. Các loại số nguyên không dấu được đảm bảo tuân theo các quy tắc này trong mọi trường hợp không liên quan đến chuyển đổi sang hoặc từ bất kỳ loại số nào khác [hoặc các loại không dấu có kích thước khác nhau] và đảm bảo đó là một trong những tính năng quan trọng nhất của các loại đó. Trong một số trường hợp, đáng để từ bỏ khả năng đại diện cho số âm để đổi lấy các đảm bảo bổ sung chỉ các loại không dấu có thể cung cấp. Các loại dấu phẩy động, cho dù có ký hay không, không thể tuân thủ tất cả các quy tắc của vòng đại số [ví dụ: chúng không thể đảm bảo rằng X + YY sẽ bằng X], và thực tế là IEEE không ' thậm chí cho phép họ tuân thủ các quy tắc của một lớp tương đương [bằng cách yêu cầu các giá trị nhất định so sánh không bằng nhau với chính chúng]. Tôi không nghĩ rằng loại dấu phẩy động "không dấu" có thể tuân theo bất kỳ tiên đề nào mà loại dấu phẩy động thông thường không thể, vì vậy tôi không chắc nó sẽ mang lại lợi thế gì.


1

IHMO bởi vì việc hỗ trợ cả hai loại dấu phẩy động có dấu và không dấu trong cả phần cứng hoặc phần mềm sẽ quá rắc rối

Đối với các loại nguyên chúng ta có thể sử dụng các giống đơn vị logic cho cả hai hoạt động số nguyên signed và unsigned trong hầu hết các tình huống sử dụng tài sản tốt đẹp của sự bổ sung 2, bởi vì kết quả là giống hệt nhau trong những trường hợp cho add, sub, không mở rộng mul và hầu hết các hoạt động trên bit. Đối với các hoạt động phân biệt giữa phiên bản đã ký và chưa ký, chúng tôi vẫn có thể chia sẻ phần lớn logic . Ví dụ

  • Sự thay đổi số học và logic chỉ cần một thay đổi nhỏ trong bộ đệm cho các bit trên cùng
  • Mở rộng phép nhân có thể sử dụng cùng một phần cứng cho phần chính và sau đó một số logic riêng biệt để điều chỉnh kết quả để thay đổi dấu hiệu . Không phải là nó được sử dụng trong bội số thực nhưng có thể làm được
  • So sánh đã ký có thể được chuyển đổi thành so sánh không dấu và ngược lại một cách dễ dàng bằng cách chuyển đổi bit trên cùng hoặc thêmINT_MIN . Về mặt lý thuyết là có thể, nó có thể không được sử dụng trên phần cứng, nhưng nó hữu ích trên các hệ thống chỉ hỗ trợ một loại so sánh (như 8080 hoặc 8051)

Các hệ thống sử dụng phần bù 1 cũng chỉ cần một chút sửa đổi cho logic bởi vì nó chỉ đơn giản là bit mang được bao bọc đến bit ít quan trọng nhất. Không chắc chắn về các hệ thống cường độ ký hiệu nhưng có vẻ như chúng sử dụng phần bù 1 trong nội bộ nên điều tương tự cũng được áp dụng

Thật không may, chúng tôi không xa xỉ cho các loại dấu phẩy động. Chỉ cần giải phóng bit dấu, chúng ta sẽ có phiên bản không dấu. Nhưng sau đó chúng ta nên sử dụng bit đó để làm gì?

  • Tăng phạm vi bằng cách thêm nó vào số mũ
  • Tăng độ chính xác bằng cách thêm nó vào lớp phủ. Điều này thường hữu ích hơn, vì chúng ta thường cần độ chính xác cao hơn phạm vi

Nhưng cả hai lựa chọn đều cần một bộ cộng lớn hơn để phù hợp với phạm vi giá trị rộng hơn. Điều đó làm tăng độ phức tạp của logic trong khi phần trên của phần bổ sung nằm ở đó không được sử dụng hầu hết thời gian. Thậm chí sẽ cần nhiều mạch hơn cho phép nhân, chia hoặc các hoạt động phức tạp khác

Trên các hệ thống sử dụng phần mềm dấu phẩy động, bạn cần 2 phiên bản cho mỗi chức năng không được mong đợi trong thời gian bộ nhớ quá đắt hoặc bạn phải tìm một số cách "khó khăn" để chia sẻ các phần của chức năng đã ký và chưa ký

Tuy nhiên phần cứng dấu phẩy động tồn tại từ lâu trước khi C được phát minh , vì vậy tôi tin rằng sự lựa chọn trong C là do thiếu hỗ trợ phần cứng vì lý do tôi đã đề cập ở trên

Điều đó nói rằng, tồn tại một số định dạng dấu phẩy động không dấu đặc biệt , chủ yếu cho mục đích xử lý ảnh, như kiểu dấu phẩy động 10 và 11 bit của nhóm Khronos


0

Tôi nghi ngờ đó là bởi vì các bộ xử lý cơ bản được nhắm mục tiêu bởi trình biên dịch C không có cách xử lý tốt với các số dấu phẩy động không dấu.


Các bộ xử lý cơ bản có cách xử lý tốt với các số dấu phẩy động đã ký không? C đã trở nên phổ biến khi các bộ xử lý phụ trợ dấu phẩy động là đơn giản và hầu như không phổ biến.
David Thornley

1
Tôi không biết tất cả các mốc thời gian lịch sử nhưng đã có hỗ trợ phần cứng mới nổi cho các số float đã ký, mặc dù hiếm khi bạn chỉ ra. Các nhà thiết kế ngôn ngữ có thể kết hợp hỗ trợ cho nó trong khi phụ trợ trình biên dịch có các mức hỗ trợ khác nhau tùy thuộc vào kiến ​​trúc được nhắm mục tiêu.
Brian Consink

0

Câu hỏi hay.

Nếu, như bạn nói, nó chỉ dành cho các cảnh báo thời gian biên dịch và không có thay đổi nào trong hành vi của chúng nếu không thì phần cứng cơ bản không bị ảnh hưởng và do đó nó sẽ chỉ là thay đổi C ++ / Trình biên dịch.

Tôi đã giành được chiến thắng tương tự trước đây, nhưng điều này là: Nó sẽ không giúp được gì nhiều. Tốt nhất trình biên dịch có thể tìm các bài tập tĩnh.

unsigned float uf { 0 };
uf = -1f;

Hoặc tối giản lâu hơn

unsigned float uf { 0 };
float f { 2 };
uf -= f;

Nhưng đó là về nó. Với các kiểu số nguyên không dấu, bạn cũng có được một hàm xác định, cụ thể là nó hoạt động giống như số học mô-đun.

unsigned char uc { 0 };
uc -= 1;

sau này 'uc' giữ giá trị 255.

Bây giờ, trình biên dịch sẽ làm gì với cùng một kịch bản được cung cấp kiểu float không dấu? Nếu các giá trị không biết tại thời điểm biên dịch, nó sẽ cần tạo mã trước tiên thực hiện các phép tính và sau đó thực hiện kiểm tra ký hiệu. Nhưng điều gì xảy ra khi kết quả của một tính toán như vậy sẽ là "-5,5" - giá trị nào sẽ được lưu trữ trong một float được khai báo không dấu? Người ta có thể thử số học mô-đun như đối với các loại tích phân, nhưng điều đó đi kèm với các vấn đề riêng của nó: Giá trị lớn nhất là vô cùng .... không hoạt động, bạn không thể có "vô cùng - 1". Đi đến giá trị khác biệt lớn nhất mà nó có thể nắm giữ cũng sẽ không thực sự hoạt động khi bạn chạy vào đó. "NaN" sẽ là một ứng cử viên.

Cuối cùng, điều này sẽ không thành vấn đề với các số điểm cố định vì có modulo được xác định rõ.

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.