Qt - custom decimal point and thousand separator
Asked Answered
T

6

12

How can I convert a number (double) to string, with custom decimal point and thousand separator chars?

I've seen QLocale, but I don't want to choose the localization country, but rather specify my own decimal point and thousand separator chars.

Thanks

Teresiateresina answered 17/2, 2011 at 22:14 Comment(2)
I can't help but ask - why is it necessary to use custom separators? Are you parsing a list and forced to use decimals (or periods) for delimiters?Daysidayspring
Since it's math app client wants options to specify custom decimal point and thousand separator chars. Why these irrelevant questions...Teresiateresina
M
15

Qt doesn't support custom locale. But to deal with just group and decimal point characters is trivial:

const QLocale & cLocale = QLocale::c();
QString ss = cLocale.toString(yourDoubleNumber, 'f');
ss.replace(cLocale.groupSeparator(), yourGroupChar);
ss.replace(cLocale.decimalPoint(), yourDecimalPointChar);

BTW, spbots' question is not irrelevant. More detail about the goal always helps and it could lead to different approach that may serve you better.

Mcmullin answered 20/2, 2011 at 16:20 Comment(1)
This code fails if, for example, one wants to use German notation (using . as group separator and , as a decimal point).Olympia
P
5

Here is how you do it just using the std::lib (no QT). Define your own numpunct-derived class which can specify decimal point, grouping character, and even the spacing between groupings. Imbue an ostringstream with a locale containing your facet. Set the flags on that ostringstream as desired. Output to it and get the string from it.

#include <locale>
#include <sstream>
#include <iostream>

class my_punct
    : public std::numpunct<char>
{
protected:
    virtual char do_decimal_point() const {return ',';}
    virtual char do_thousands_sep() const {return '.';}
    virtual std::string do_grouping() const  {return std::string("\2\3");}
};

int main()
{
    std::ostringstream os;
    os.imbue(std::locale(os.getloc(), new my_punct));
    os.precision(2);
    fixed(os);
    double x = 123456789.12;
    os << x;
    std::string s = os.str();
    std::cout << s << '\n';
}

1.234.567.89,12

Payday answered 20/2, 2011 at 18:13 Comment(1)
And for a Unicode-based thousands separator, e.g. Narrow No-Break Space U+202F, you can use std::basic_stringstream<wchar_t>, std::numpunct<wchar_t> and std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>. Live example here.Holmquist
T
5

The easiest way is to use arg of QString.

QString str = QString("%L1").arg(yourDouble);
Torchbearer answered 21/12, 2018 at 9:12 Comment(0)
H
3

for qml users:

function thousandSeparator(input){
    return input.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
}
Hild answered 4/7, 2016 at 8:34 Comment(2)
Although this code may be help to solve the problem, providing additional context regarding why and/or how it answers the question would significantly improve its long-term value. Please edit your answer to add some explanation.Standing
The answer is perfectly appropriate for me the way it is. Thank you!Deangelis
D
0

Since you don't want QLocale perhaps you could do a simple conversion (with QString::number, for example) and then replace the desired characters afterwards.

Devon answered 17/2, 2011 at 23:0 Comment(0)
H
0

pretty horrible, but got the job done

double doubleNumber = 5234556.3545;
int precision = 2;

QString stringNumber = QString::number(doubleNumber, 'f', precision);

for(int point = 0, i = (stringNumber.lastIndexOf('.') == -1 ? stringNumber.length() : stringNumber.lastIndexOf('.')); i > 0; --i, ++point)
{
    if(point != 0 && point % 3 == 0)
    {
        stringNumber.insert(i, ',');
    }
}
Harassed answered 18/2, 2011 at 16:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.