-1

I was trying to format a matrix using stringstream, setw and setprecision. The code looks like this:

template <typename T>
std::string format(std::vector<T> &a, int m, int n, int lda)
{
    std::stringstream ss;
    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++)
        {
            ss << std::setw(6);
            ss << a[i + j * lda];
            ss << std::setprecision(2);
        }
        if (i < m - 1)
            ss << std::endl;
    }
    return ss.str();
}

int main()
{
    const int LDA = 5;
    const int N = LDA;

    std::vector<double> a = {
        6.39, 0.00, 0.00, 0.00, 0.00,
        0.13, 8.37, 0.00, 0.00, 0.00,
        -8.23, -4.46, -9.58, 0.00, 0.00,
        5.71, -6.10, -9.25, 3.72, 0.00,
        -3.18, 7.21, -7.42, 8.54, 2.51};

    std::cout << format(a, N, N, LDA) << std::endl;

    return 0;
}

The output looks like this:

  6.39  0.13  -8.2   5.7  -3.2
     0   8.4  -4.5  -6.1   7.2
     0     0  -9.6  -9.2  -7.4
     0     0     0   3.7   8.5
     0     0     0     0   2.5
  1. Why are values like -8.2, 8.4 rounded?
  2. Why aren't zeros formatted?

I was expecting an output like this:

   6.39   0.13  -8.23   5.71  -3.18
   0.00   8.37  -4.46  -6.10   7.21
   0.00   0.00  -9.58  -9.25  -7.42
   0.00   0.00   0.00   3.72   8.54
   0.00   0.00   0.00   0.00   2.51

How do I format it correctly?

ramgorur
  • 2,104
  • 4
  • 26
  • 39
  • 1
    Try set a fixed format: `ss << std::fixed;`. – Evg Jun 14 '23 at 21:40
  • Side note: one thing you'll quickly notice is floating point numbers are rarely exactly the number you think they are. Wrangling them into the correct format can be an absolute . – user4581301 Jun 14 '23 at 21:47

1 Answers1

2

You need to move std::setprecision(2) to before you start printing, otherwise the first value will have the default precision. This setting is active until you replace it with something else, so you only need to do it once.

You also need to set the stream in std::fixed mode.

Example:

template <typename T>
std::string format(std::vector<T> &a, int m, int n, int lda) {
    std::stringstream ss;
    
    ss << std::fixed << std::setprecision(2);    // <- here

    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            ss << std::setw(6) << a[i + j * lda];
        }
        if (i < m - 1) ss << '\n'; // std::endl; is pointless
    }
    return ss.str();
}

Demo

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108