2016-12-19 69 views
5

Tôi đang cố in tối đa 4 chữ số sau dấu thập phân trong C++ (Sử dụng luồng). Vì vậy, nếu số lượng không cần 4 chữ số sau số thập phân tôi muốn nó chỉ sử dụng số thập phân mà nó thực sự cần.In tối đa 4 số thập phân

Ví dụ:

1.12345 -> 1.1234 
1.0  -> 1 
1.12  -> 1.12 
1.12345789 -> 1.1234 
123.123 -> 123.123 
123.123456 -> 123.1234 

tôi đã cố gắng std::setprecision(4) nhưng mà bộ số lượng đáng kể chữ số và thất bại trong trường hợp kiểm tra:

123.123456 gives 123.1 

Tôi cũng đã cố gắng đưa ra std::fixed cùng với std::setprecision(4) nhưng đó đưa ra một số chữ số cố định sau số thập phân ngay cả khi không cần:

1.0 gives 1.0000 

Có vẻ như std::defaultfloat là cái tôi cần và không cố định cũng như không theo cấp số mũ. Nhưng nó dường như không in số chữ số sau thập phân một cách thích hợp và chỉ có một tùy chọn cho các chữ số có nghĩa.

+4

Điều này sẽ yêu cầu mã tùy chỉnh, làm việc trên một biểu diễn BCD hoặc chuỗi của giá trị được in. Lưu ý rằng, bởi vì biểu diễn bên dưới của số dấu phẩy động là nhị phân, không nhất thiết phải là một biểu diễn nhị phân chính xác (nói) 123.123. Nếu bạn hiển thị đủ số thập phân, cái gì đó như 'double x = 123.123; cout << x' có thể xuất ra một cái gì đó như '123.1230000001'. Do đó, tôi khuyên bạn nên viết một hàm chuyển đổi số double thành chuỗi có bốn chữ số thập phân và sau đó xóa bất kỳ số 0 dấu sau dấu thập phân trước khi trả về chuỗi. – Simon

+0

Ví dụ của bạn không khớp với mô tả sự cố của bạn. Nhìn vào những ví dụ đó, nó giống như bạn muốn không quá 4 số thập phân, mà không có bất kỳ dấu 0 nào. Điều đó chắc chắn không giống như chính xác 4 số thập phân. Bên cạnh đó, như được chỉ ra bởi Simon, với bản chất của việc thể hiện các giá trị điểm nổi IEEE, bạn sẽ phải tạo ra một đặc điểm kỹ thuật tốt hơn cho cụm từ * "cần chữ số" * được cho là có ý nghĩa gì. – IInspectable

+2

[Điều mà mọi nhà khoa học máy tính cần biết về số học dấu chấm động] (https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) có lẽ là bắt buộc phải đọc. – IInspectable

Trả lời

4

Chúng tôi có thể thực hiện việc này bằng cách sử dụng std::stringstreamstd::string. Chúng tôi chuyển số double vào luồng định dạng như chúng tôi nếu chúng tôi gửi nó đến cout. Sau đó, chúng tôi kiểm tra chuỗi chúng tôi nhận được từ luồng để xem liệu có dấu 0 hay không. Nếu có chúng ta loại bỏ chúng. Một khi chúng ta làm điều đó, chúng ta kiểm tra xem liệu chúng ta có còn dấu chấm thập phân hay không, nếu chúng ta sau đó chúng ta cũng loại bỏ điều đó. Bạn có thể sử dụng một cái gì đó như thế này:

int main() 
{ 
    double values[] = { 1.12345, 1.0, 1.12, 1.12345789, 123.123, 123.123456, 123456789, 123.001 }; 
    std::vector<std::string> converted; 
    for (auto e : values) 
    { 
     std::stringstream ss; 
     ss << std::fixed << std::setprecision(4) << e; 
     std::string value(ss.str()); 
     if (value.find(".") != std::string::npos) 
     { 
      // erase trailing zeros 
      while (value.back() == '0') 
       value.erase(value.end() - 1); 
      // if we are left with a . at the end then get rid of it 
      if (value.back() == '.') 
       value.erase(value.end() - 1); 
      converted.push_back(value); 
     } 
     else 
      converted.push_back(value); 
    } 
    for (const auto& e : converted) 
     std::cout << e << "\n"; 
} 

nào khi được chuyển thể thành running example cho

1.1235 
1 
1.12 
1.1235 
123.123 
123.1235 
123456789 
123.001 
1

Sử dụng câu trả lời từ here cùng với logic tùy chỉnh để loại bỏ các số không và điểm:

#include <iostream> 
#include <iomanip> 
#include <sstream> 
#include <string> 
#include <vector> 
#include <iterator> 
#include <algorithm> 

std::string remove_zeros(std::string numberstring) 
{ 
    auto it = numberstring.end() - 1; 
    while(*it == '0') { 
     numberstring.erase(it); 
     it = numberstring.end() - 1; 
    } 
    if(*it == '.') numberstring.erase(it); 
    return numberstring; 
} 

std::string convert(float number) 
{ 
    std::stringstream ss{}; 
    ss << std::setprecision(4) << std::fixed << std::showpoint << number; 
    std::string numberstring{ss.str()}; 
    return remove_zeros(numberstring); 
} 

int main() 
{ 
    const float values[]{1.12345, 1.0, 1.12, 1.12345789, 147323.123, 123.123456}; 
    for(auto i : values) 
     std::cout << convert(i) << '\n'; 
} 

sản xuất:

1.1235 
1 
1.12 
1.1235 
147323.125 
123.1235 
Các vấn đề liên quan