Làm cách nào để bạn chuyển đổi một số thực thành một chuỗi trong C ++ trong khi chỉ định độ chính xác và số lượng các chữ số thập phân?
Ví dụ: 3.14159265359 -> "3.14"
Làm cách nào để bạn chuyển đổi một số thực thành một chuỗi trong C ++ trong khi chỉ định độ chính xác và số lượng các chữ số thập phân?
Ví dụ: 3.14159265359 -> "3.14"
Câu trả lời:
Một cách điển hình sẽ là sử dụng stringstream
:
#include <iomanip>
#include <sstream>
double pi = 3.14159265359;
std::stringstream stream;
stream << std::fixed << std::setprecision(2) << pi;
std::string s = stream.str();
Xem đã sửa
Sử dụng ký hiệu dấu phẩy động cố định
Đặt
floatfield
cờ định dạng cho luồng str thànhfixed
.Khi
floatfield
được đặt thànhfixed
, giá trị dấu phẩy động được viết bằng ký hiệu dấu chấm cố định: giá trị được biểu thị bằng chính xác bao nhiêu chữ số trong phần thập phân như được chỉ định bởi trường chính xác (precision
) và không có phần số mũ.
và thiết lập chính xác .
Đối với các chuyển đổi có mục đích kỹ thuật , như lưu trữ dữ liệu trong tệp XML hoặc JSON, C ++ 17 xác định họ hàm to_chars .
Giả sử một trình biên dịch tuân thủ (mà chúng tôi thiếu tại thời điểm viết bài), một cái gì đó như thế này có thể được coi là:
#include <array>
#include <charconv>
double pi = 3.14159265359;
std::array<char, 128> buffer;
auto [ptr, ec] = std::to_chars(buffer.data(), buffer.data() + buffer.size(), pi,
std::chars_format::fixed, 2);
if (ec == std::errc{}) {
std::string s(buffer.data(), ptr);
// ....
}
else {
// error handling
}
Phương pháp thông thường để thực hiện loại điều này là "in thành chuỗi". Trong C ++, điều đó có nghĩa là sử dụng std::stringstream
một cái gì đó như:
std::stringstream ss;
ss << std::fixed << std::setprecision(2) << number;
std::string mystring = ss.str();
Một lựa chọn khác là snprintf
:
double pi = 3.1415926;
std::string s(16, '\0');
auto written = std::snprintf(&s[0], s.size(), "%.2f", pi);
s.resize(written);
Bản trình diễn . Xử lý lỗi nên được thêm vào, tức là kiểm trawritten < 0
.
snprintf
tốt hơn trong trường hợp này? Vui lòng giải thích ... Nó chắc chắn sẽ không nhanh hơn, tạo ra ít mã hơn [Tôi đã viết một triển khai printf, nó khá nhỏ gọn chỉ dưới 2000 dòng mã, nhưng với việc mở rộng macro lên đến khoảng 2500 dòng]
__printf_fp
chức năng cơ bản - thật kỳ lạ là nó mất nhiều thời gian hơn stringstream
, vì nó thực sự không nên.
Bạn có thể sử dụng fmt::format
hàm từ thư viện {fmt} :
#include <fmt/core.h>
int main()
std::string s = fmt::format("{:.2f}", 3.14159265359); // s == "3.14"
}
nơi 2
là chính xác.
Cơ sở định dạng này đã được đề xuất để chuẩn hóa trong C ++: P0645 . Cả P0645 và {fmt} đều sử dụng cú pháp chuỗi định dạng giống Python tương tự như printf
's nhưng sử dụng {}
làm dấu phân tách thay vì %
.
Đây là một giải pháp chỉ sử dụng std. Tuy nhiên, lưu ý rằng điều này chỉ làm tròn xuống.
float number = 3.14159;
std::string num_text = std::to_string(number);
std::string rounded = num_text.substr(0, num_text.find(".")+3);
Vì rounded
nó mang lại:
3.14
Mã chuyển đổi toàn bộ số float thành chuỗi, nhưng cắt tất cả các ký tự 2 ký tự sau dấu "."
number + 0.005
trong trường hợp của tôi.
Ở đây tôi cung cấp một ví dụ phủ định mà bạn muốn tránh khi chuyển đổi số động thành chuỗi.
float num=99.463;
float tmp1=round(num*1000);
float tmp2=tmp1/1000;
cout << tmp1 << " " << tmp2 << " " << to_string(tmp2) << endl;
Bạn lấy
99463 99.463 99.462997
Lưu ý: biến num có thể là bất kỳ giá trị nào gần với 99,463, bạn sẽ nhận được bản in tương tự. Vấn đề là tránh dùng hàm "to_string" trong c ++ 11. Tôi đã mất một lúc để thoát ra khỏi cái bẫy này. Cách tốt nhất là phương thức stringstream và sprintf (ngôn ngữ C). C ++ 11 hoặc mới hơn phải cung cấp tham số thứ hai là số chữ số sau dấu phẩy động để hiển thị. Ngay bây giờ, mặc định là 6. Tôi đang đăng điều này để những người khác không mất thời gian cho chủ đề này.
Tôi đã viết phiên bản đầu tiên của mình, vui lòng cho tôi biết nếu bạn tìm thấy bất kỳ lỗi nào cần được sửa. Bạn có thể kiểm soát hành vi chính xác với iomanipulator. Chức năng của tôi là để hiển thị số chữ số sau dấu thập phân.
string ftos(float f, int nd) {
ostringstream ostr;
int tens = stoi("1" + string(nd, '0'));
ostr << round(f*tens)/tens;
return ostr.str();
}