i'm writing a double value to a file. The numeric value is written with a point as a decimal separator. I would like to use a comma. How i can do that?
The usual way is to use a locale with the decimal separator set to the comma. If your machine is configured for that generally, you can probably just use the nameless locale for it:
std::cout.imbue(std::locale(""));
std::cout << 12345.67;
You can find the answer in an earlier question
This basically changes the locale used by the streams you are using.
I think in the library cmath
there is a function called modf which takes a float or double, and a pointer to an float or double, and returns an integer.
double intPart;
double fractPart;
fractPart = modf(doubleValue, &intPart);
So you pass in the double value, it returns the decimal part as an integer, and the integer value is stored in the pointer you passed in.
You could then write these to file however you want, with a comma in the middle or whatever, just write it as two separate numbers.
float or double
Related
I dont' have much experience with C++, I have the following problem.
With the following code :
double d = 0.0000000;
stringstream ss;
ss << std::fixed << std::setprecision( 2 ) << d;
ss >> d;
or
std::string content = ss.str();
d = atof( content.c_str() );
Either of the two ways while debuging in MS Visual Studio , I see the value of d is 0.0000000 not 0.00 as in the string content
How do I get exact content of string assigned to double d?
May be I should ask a broader question :
I am writing a method that returns a double with precision as needed. For example if I have 2.446343434 as value of d and precision is 2, how can I get my method return d as 2.45 ?
After reading the below answers : I came to know that it is not possible to do such thing. So the next question is :
Even if my above code tries to put 2.45 into double, the C++ runtime will append zeros ( how many ? ) to 2.45 and return right? Is there a way to control appending zeros to the double?
I see the value of d is 0.0000000 not 0.00 as in the string
But both of those numbers have exactly the same value. So, a number can have the value 0.0000000 if and only if it also has the value 0.00.
How do I get exact content of string assigned to double d?
You cannot. double represents a numeric value. It does not represent a character string.
Also, in more general, that is not possible because floating point numbers cannot represent all the numbers that can be represented by a character string. But that is not a problem with 0, which is indeed representable.
I am writing a method that returns a double with precision as needed. For example if I have 2.446343434 as value of d and precision is 2, how can I get my method return d as 2.45
You cannot get your method to return a double with the value 2.45 unless the format of the double can represent 2.45. The binary64 format specified by IEEE 754 can not represent 2.45. In such case, the best that you can do, is to return the representable number closest to the number with 2 significant fractional digits, which in the case of IEEE 754 would be 2.45000000000000017763568394003. The program in your question achieves that.
If that's not what you want, then floating point is not appropriate for your use case.
The human-readable value for d that you're seeing in the debugger, "0.0000000", is just a representation, and a fairly arbitrary one at that. The actual double object does not store this string, nor anything with a fixed number of decimal places.
Its actual identity, at the lowest level, is (a) in binary, (b) encoded according to the floating-point specification, and (c) irrelevant for your purposes. The value is zero; period.
The debugger has simply chosen to use seven decimal places when converting the number into something you can read with your eyes and brain. When using printf or std::cout to similarly output the number for reading, you can pick some other format if you like, including a format with two decimal places to match your original string input. That's just different ways of saying the same thing.
Do not confuse value with representation.
Also, your insistence on specifically two decimal places makes me suspicious: if you're planning on using double to store currency, just don't. Floating-point types are not appropriate for that.
I'm trying to write a wrapper to ADO.
A DECIMAL is one type a COM VARIANT can be, when the VARIANT type is VT_DECIMAL.
I'm trying to put it in c native data type, and keep the variable value.
it seem that the correct type is long double, but I get "no suitable conversion error".
For example:
_variant_t v;
...
if(v.vt == VT_DECIMAL)
{
double d = (double)v; //this works but I'm afraid can be loss of data...
long double ld1 = (long double)v; //error: more then one conversion from variant to long double applied.
long double ld2 = (long double)v.decVal; //error: no suitable conversion function from decimal to long double exist.
}
So my questions are:
is it totally safe to use double to store all possible decimal values?
if not, how can I convert the decimal to a long double?
How to convert a decimal to string? (using the << operator, sprintf is also good for me)
The internal representation for DECIMAL is not a double precision floating point value, it is integer instead with sign/scale options. If you are going to initialize DECIMAL parts, you should initialize these fields - 96-bit integer value, scale, sign, then you get valid decimal VARIANT value.
DECIMAL on MSDN:
scale - The number of decimal places for the number. Valid values are from 0 to 28. So 12.345 is represented as 12345 with a scale of 3.
sign - Indicates the sign; 0 for positive numbers or DECIMAL_NEG for negative numbers. So -1 is represented as 1 with the DECIMAL_NEG bit set.
Hi32 - The high 32 bits of the number.
Lo64 - The low 64 bits of the number. This is an _int64.
Your questions:
is it totally safe to use double to store all possible decimal values?
You cannot initialize as double directly (e.g. VT_R8), but you can initialize as double variant and use variant conversion API to convert to VT_DECIMAL. A small rounding can be applied to value.
if not, how can I convert the decimal to a long double?
How to convert a decimal to string? (using the << operator, sprintf is also good for me)
VariantChangeType can convert decimal variant to variant of another type, including integer, double, string - you provide the type to convert to. Vice versa, you can also convert something different to decimal.
"Safe" isn't exactly the correct word, the point of DECIMAL is to not introduce rounding errors due to base conversions. Calculations are done in base 10 instead of base 2. That makes them slow but accurate, the kind of accuracy that an accountant likes. He won't have to chase a billionth-of-a-penny mismatches.
Use _variant_t::ChangeType() to make conversions. Pass VT_R8 to convert to double precision. Pass VT_BSTR to convert to a string, the kind that the accountant likes. No point in chasing long double, that 10-byte FPU type is history.
this snippets is taken from http://hackage.haskell.org/package/com-1.2.1/src/cbits/AutoPrimSrc.c
the Hackage.org says:
Hackage is the Haskell community's central package archive of open
source software.
but please check the authors permissions
void writeVarWord64( unsigned int hi, unsigned int lo, VARIANT* v )
{
ULONGLONG r;
r = (ULONGLONG)hi;
r >>= 32;
r += (ULONGLONG)lo;
if (!v) return;
VariantInit(v);
v->vt = VT_DECIMAL;
v->decVal.Lo64 = r;
v->decVal.Hi32 = 0;
v->decVal.sign = 0;
v->decVal.scale = 0;
}
If I understood Microsoft's documentation (https://msdn.microsoft.com/en-us/library/cc234586.aspx) correctly, VT_DECIMAL is an exact 92-bit integer value with a fixed scale and precision. In that case you can't store this without loss of information in a float, a double or a 64-bit integer variable.
You're best bet would be to store it in a 128-bit integer like __int128 but I don't know the level of compiler support for it. I'm also not sure you will be able to just cast one to the other without resorting to some bit manipulations.
Is it totally safe to use double to store all possible decimal values?
It actually depends what you mean by safe. If you mean "is there any risk of introducing some degree of conversion imprecision?", yes there is a risk. The internal representations are far too different to guarantee perfect conversion, and conversion noise is likely to be introduced.
How can I convert the decimal to a long double / a string?
It depends (again) of what you want to do with the object:
For floating-point computation, see #Gread.And.Powerful.Oz's link to the following answer: C++ converting Variant Decimal to Double Value
For display, see MSDN documentation on string conversion
For storage without any conversion imprecision, you should probably store the decimal as a scaled integer of the form pair<long long,short>, where first holds the 96-bits mantissa and second holds the number of digits to the right of the decimal point. This representation is as close as possible to the decimal's internal representation, will not introduce any conversion imprecision and won't waste CPU resources on integer-to-string formatting.
i have following part of code:
string v;
getline(linestream,v,' ');
double d=atof(v.c_str());
fprintf(writeFile3,"%f\n",(double)d);
but lets say first line has value 0.08012901 but d=0.080129 last 2 values are omitted, how can i get full double value?
Thank you
If you want the digits copied exactly, by far the easiest way to go is to just leave the digits in string form:
string v;
getline(instream, v, ' ');
outstream << v;
Almost anything that converts the digits to a double, then prints out the value has at least some chance of producing a result that's slightly different from the input.
It's not that the decimal places are not stored in the d. It's just that fprintf only prints 6 decimal places by default. To print 8, try
fprintf(writeFile3, "%.8f\n", d);
You don't have to cast d as a double since it already is of type double.
I would add to the answer above that whatever you put after the variable call is what you will display. By default C++ will show 6.
ie
fprintf(writeFile3, "%.3f\n", (double)d); will display 3 decimal points at the end. It will also pad so if there is possible for longer than 8 decimal places you will want to make it more than that. That I know of you cannot set a flag to just display all decimal points. It has to be explicit.
I am facing a conversion issue for which I'd like your help. I'm using gcc4 compiler and I am quite restricted to use gcc4.
I want to convert std::string to double.
std::string aQuantity = aRate.getQuantity();
std::string aAmount = aRate.getAmount();
// aAmount = "22.05"
double dQuantity = boost::lexical_cast<double>(aQuantity);
double dAmount = boost::lexical_cast<double> (aAmount);
// dAmount = 22.050000000000001
By the way, I also tried atof and I still have the same issue. Is there any way to use istringstream with setprecission(2) to get the correct value shown by aAmount?
Due to the nature of floating point values, 22.050000000000001 is the closest value to 22.05 that can be stored. The same would occure if you simply tried to store 22.05 in a double and then print it.
You should set the precision on the output stream if you want to print 22.05. Alternatively you could investigate a rational number library (for example, Boost.Rational). This would be able to store the value 22.05 precisely, unlike a double (or float).
How to use set up decimal precision for all double type numbers in a large C++ program.
I can use stringstream and setprecision(n) to do it but I have to do it one by one for every double number in the whole program.
How to do it globally once for all so that all double type numbers in the program has fixed decimal digits after decimal point (e.g. 4) ?
I do not want to use function call to cause calling overhead.
thanks
double type is not designed to do what you want: it is a floating decimal type, not a fixed decimal type. What you need is some kind of decimal type, but unfortunately C++ does not yet have such type.
It can be emulated most of the times with an integer type where you assume that it represents the then-thousandths of a unit. You just have to be careful in the multiplications and divisions to fix the scale. Additions and subtractions work automatically.
setprecision does not change the precision of double values, but just the precision used when converted into a string.
And converting doubles into strings is relatively expensive operation, so the overhead of a single extra function call should be negligible. If you use double-string conversion in performance critical code, then you are doing it wrong.
My advice would be to just write a function such as:
std::string FmtDbl(double d)
{
std::ostringstream os;
os << std::setprecision(4) << d;
return os.str();
}
And use that function everywhere you need the conversion.