2012-06-28 33 views
19

Kết quả của abs (-2147483648) là -2147483648, phải không? có vẻ như không thể chấp nhận được.Tại sao giá trị tuyệt đối của số nguyên âm tối đa-2147483648 vẫn là -2147483648?

printf("abs(-2147483648): %d\n", abs(-2147483648)); 

đầu ra:

abs(-2147483648): -2147483648 
+1

Tôi tin rằng đây là hành vi không xác định. Tôi không có tiêu chuẩn C tiện dụng, vì vậy tôi không thể sao lưu nó. –

+5

Bạn mong đợi điều gì, bởi vì 'abs (int)' trả về 'int'? –

+7

Dự thảo mới nhất của C11 nói (7.21.6.1, về abs và bạn bè) "Nếu không thể đại diện cho kết quả , hành vi không xác định" –

Trả lời

18

Tiêu chuẩn nói về abs():

Các abs, labs, và llabs chức năng tính toán giá trị tuyệt đối của một số nguyên j. Nếu kết quả không thể được biểu diễn, hành vi là không xác định.

Và kết quả thực sự không thể được biểu diễn vì biểu diễn bổ sung của các số nguyên đã ký không đối xứng. Hãy suy nghĩ về nó ... Nếu bạn có 32 bit trong một số int, cung cấp cho bạn 2 giá trị khác biệt từ INT_MIN đến INT_MAX. Đó là một số chẵn các giá trị. Vì vậy, nếu chỉ có một 0, số lượng các giá trị lớn hơn 0 không thể giống với số lượng giá trị nhỏ hơn 0. Và do đó không có đối tác dương nào với INT_MIN với giá trị là - INT_MIN.

Vì vậy, điều không thể chấp nhận là gọi abs(INT_MIN) trên nền tảng của bạn.

-5

Hãy thử điều này

printf("abs(-2147483648): %u\n", abs(-2147483648)); 
+5

Điều này, bạn tôi, có hành vi không xác định. Bạn đang in một số nguyên có chữ ký với trình định dạng chưa ký. I -1 bởi vì nó hơn nữa không trả lời câu hỏi. –

10

Từ 2147483648 lớn hơn INT_MAX tình hình thực hiện của bạn, sau đó abs(-2147483648) là undefined.

5

Đây là mã trong abs.c trong mã nguồn của glibc GNU.

/* Return the absolute value of I. */ 
int 
DEFUN(abs, (i), int i) 
{ 
    return(i < 0 ? -i : i); 
} 

Vì vậy, abs (-2147483648) return - (- 2147483648). Trong x86, nó được thực hiện bởi hai hướng dẫn này

movl $-2147483648, %eax 
negl %eax 

lệnh bỏ qua được thực hiện theo cách này: num = 0-num; sbb được thực hiện theo cách này: Trích xuất nguồn từ đích và trừ 1 phần bổ sung nếu cờ Carry được đặt. Vì vậy, abs (-2147483648) (hex là 0x80000000) -> - (- 2147483648) -> 0 - (- 2147483648) trở thành (0x80000000) cuối cùng.

chi tiết về hướng dẫn negl, xin vui lòng lần http://zsmith.co/intel_n.html#neg

chi tiết về hướng dẫn SBB, vui lòng truy cập http://web.itu.edu.tr/kesgin/mul06/intel/instr/sbb.html

+0

Và? Ý tôi là, xây dựng nó? –

9

Số âm thường được biểu diễn bằng bổ sung nhị phân whit.

Để chuyển đổi tích cực đến tiêu cực nó được sử dụng luận lý

x -> not(x)+1 

Đối với 8 bit số học

01111111b là 127 và -127 trở thành
10000000b + 1 = 10000001b

và theo chiều ngược lại -127 10000001b trở thành
01111110b + 1 = 01111111b

Điều gì về -128?

-128 là 10000000b và không có đối tác tích cực của nó, bởi vì không có 128 trong 8 bit ký số học.

10000000 -> 01.111.111 + 1 = 10000000 và -128 lần nữa

Cùng áp dụng cho gốc câu hỏi

+0

đó là lý do tại sao 0 và giá trị tối thiểu luôn giống nhau sau khi phủ nhận trong phần bổ sung của hai –

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