Khi nào tôi sử dụng fabs và khi nào thì đủ để sử dụng std :: abs?


100

Tôi cho rằng điều đó absfabsđang hoạt động khác khi sử dụng math.h. Nhưng khi tôi sử dụng just cmathand std::abs, tôi có phải sử dụng std::fabshay fabskhông? Hay điều này không được xác định?

Câu trả lời:


124

Trong C ++, nó luôn đủ để sử dụng std::abs; nó bị quá tải đối với tất cả các loại số.

Trong C, abschỉ hoạt động trên số nguyên và bạn cần fabsgiá trị dấu phẩy động. Chúng có sẵn trong C ++ (cùng với tất cả thư viện C), nhưng không cần phải sử dụng chúng.


Đây có phải là trường hợp trên mọi nền tảng không? Esp. Windows và Mac OS X? Hay ít nhất là theo tiêu chuẩn C ++?
toán học

3
@brubelsabs: vâng. Không cần một hàm fabs riêng biệt trong C ++ vì C ++ có tính năng nạp chồng hàm (abs có thể được định nghĩa cho nhiều kiểu và nó nằm trong C ++). Nó cũng được đảm bảo theo tiêu chuẩn. Tất nhiên nếu bạn tìm kiếm một số trình biên dịch lỗi thời hơn 10 năm tuổi, bạn có thể tìm thấy một trình biên dịch không hỗ trợ nó.
stinky472,

1
Đó là trong ++ Chuẩn C, vì vậy nó là trường hợp trên mọi nền tảng với một trình biên dịch đàng hoàng, bao gồm cả Windows và Mac OS X. khoản 26,5 nói rằng, ngoài các intphiên bản từ thư viện C, có quá tải cho long, float, doublelong double. Mệnh đề 26.2.7 cũng định nghĩa quá tải cho complex.
Mike Seymour

6
Nếu bạn quên std::và chỉ sử dụng abs, mã của bạn sẽ hoạt động như mong đợi trên windows nhưng sẽ sử dụng intphiên bản trên linux, có thể rất khó gỡ lỗi.
Adversus

" tất cả các loại số" [cần dẫn nguồn]. Tôi có thể thấy int, long, long long, std :: intmax_t, float, double, long double. Không có phiên bản ngắn hoặc ký tự nào (hoặc phiên bản không dấu) mà tôi có thể thấy.
user673679

23

Vẫn có thể sử dụng đối số fabsfor doublefloat. Tôi thích điều này hơn vì nó đảm bảo rằng nếu tôi vô tình loại bỏ dấu std::hiệu abs, hành vi vẫn giữ nguyên đối với các đầu vào dấu chấm động.

Tôi vừa dành 10 phút để gỡ lỗi vấn đề này, do lỗi của chính tôi khi sử dụng absthay vì std::abs. Tôi giả định rằng điều đó using namespace std;sẽ suy ra std::absnhưng nó không xảy ra, và thay vào đó là sử dụng phiên bản C.

Dù sao, tôi tin rằng việc sử dụng fabsthay vì abscho đầu vào dấu phẩy động là một cách tốt để ghi lại ý định của bạn một cách rõ ràng.


2
Lạ nhỉ. Cuộc gọi của bạn nên không rõ ràng (và do đó là một lỗi) phải không?
Nick

Bạn không nên sử dụng fabsf cho float? Vì vậy, tôi không nghĩ chúng giống hệt nhau.
Nick

Hãy cẩn thận với Android NDK g ++, nó cũng nhường cho hàm c abs () thay vì std :: abs (). Tuy nhiên, trong trình biên dịch c ++ Visual Studio, tuy nhiên abs luôn trỏ đến std :: abs ().
Southerton

@Nick, tôi nghĩ tôi đồng ý với bạn: Tôi dường như không hiểu hành vi đó của Alan Turing, tức là đối với tôi, quá tải std::absdường như luôn được gọi (và không phải phiên bản C của abs) khi gọi absmiễn là using namespace std;được giải thích ở bắt đầu. Tôi không biết liệu đây có phải là trình biên dịch cụ thể hay không.
MaviPranav

@Nick không phải là lỗi vì có tên hàm phù hợp. Việc thực hiện được xác định cái nào sẽ được chọn.
Pato Sandaña,

11

Có một lý do nữa để đề xuất std::fabscho các đầu vào dấu phẩy động một cách rõ ràng.

Nếu bạn quên bao gồm <cmath>, bạn std::abs(my_float_num)có thể std::abs(int)thay thế bằng std::abs(float). Thật khó để nhận thấy.


1

"abs" và "fabs" chỉ giống nhau đối với các kiểu float của C ++, khi chúng có thể được dịch mà không có thông báo quá tải không rõ ràng.

Tôi đang sử dụng g ++ (g ++ - 7). Cùng với việc sử dụng mẫu và đặc biệt là khi sử dụng mpreal, có những trường hợp có thông báo "quá tải không rõ ràng" - abs(static_cast<T>(x))không phải lúc nào cũng giải quyết được điều đó. Khi cơ bụng không rõ ràng, có khả năng fabs đang hoạt động như mong đợi. Đối với sqrt, tôi không tìm thấy lối thoát nào đơn giản như vậy.

Kể từ nhiều tuần tôi đang vật lộn với C ++ "không tồn tại vấn đề". Tôi đang cập nhật một chương trình C ++ cũ lên C ++ 14 để sử dụng nhiều hơn và tốt hơn so với trước đây. Thường thì cùng một tham số mẫu có thể là thực tế bất kỳ kiểu float chuẩn hoặc kiểu phức tạp hoặc kiểu lớp. Tại sao từ trước đến nay, đôi dài hành động có phần hợp lý hơn các loại khác. Tất cả đều hoạt động, và tôi đã bao gồm cả mpreal trước đây. Sau đó, tôi đang đặt loại float mặc định của mình thành mpreal và gặp phải vô số lỗi cú pháp. Điều đó đã tạo ra hàng nghìn lần quá tải không rõ ràng, ví dụ như abs và sqrt, kêu gọi các giải pháp khác nhau. Một số cần các chức năng trợ giúp quá tải nhưng nằm ngoài khuôn mẫu. Phải thay thế riêng lẻ một nghìn lần sử dụng 0,0L và 1,0L bằng loại hằng số chính xác sử dụng Zero hoặc One hoặc type_cast - định nghĩa chuyển đổi tự động là không thể vì không rõ ràng.

Cho đến tháng 5, tôi nhận thấy sự tồn tại của các chuyển đổi ngầm rất tốt. Nhưng đơn giản hơn nhiều sẽ không có bất kỳ, và có các hằng số lưu kiểu với type_cast rõ ràng an toàn cho bất kỳ kiểu hằng số tiêu chuẩn nào 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.