I need to output numbers in scientific notation such that there is always a "0" before the decimal point.
e.g. For the number x = 134.87546, I need to produce the output
0.134875E03 NOT 1.348755E02
Does someone know how to do this?
Thanks in Advance --Shiraz.
int exp = (int)log10(input)+1;
double shifted = input / pow(10.0, exp);
printf("%fE%d", shifted, exp);
int exponent = floor(log10(num)) + 1;
Then just print "0.", the number without decimals, "E", then the exponent.
You may investigate using the Boost Format library which is a general output formatting library.
Related
Let's say I have an input 1.251564.
How can I find how many elements are after "." to have an output as follows:
int numFloating;
// code to go here that leads to
// numFloating == 6
p.s. Sorry for not providing any code, I just have no idea how that should be implemented :(
Thanks for your answers!
Let us consider your number, 1.251564. When you store this in a double, it is stored in the binary IEEE754 format. And you might find that the number is not representable. So, let us check for this number. The closest representable double is:
1.25156 39999 99999 89880 45035 73046 53152 82344 81811 52343 75
This probably comes as something of a surprise to you. There are 52 decimal digits following the decimal point.
The lesson that you need to take away from this is that if you want to ask questions about decimal representations, you need to use a decimal data type rather than double. Once you can actually represent the value exactly, then you will be able to reason about it in a manner that matches your expectations.
Simplest way would be to store it in string.
std::string str("1.1234");
size_t length = str.length();
size_t found = str.find('.', 0 );
size_t count = length-found-1;
int finallyGotTheCount = static_cast<int>(count);
This won't end up well. The problem is that sometimes there are float errors when representing numbers in binary (which is what your computer does).
For example, when adding 1 / 3 + 1 / 3 + 1 / 3 you might get 0.999999... and the number of decimal places varies greatly.
ravi already provided a good way to calculate it, so I'll provide a different one:
double number = 0; // should be equal to the number you want to check
int numFloating = 0;
while ((double)(int)number != number){
number *= 10;
numFloating++;
}
number is a double variable that holds the number you want to check for decimal places.
If you have a fractional number. Lets say .1234
Repeatedly multiply by 10 and throw away the integer portion of the number until you get zero. The number of steps will be the number of decimals. e.g:
.1234 * 10 = 1.234
.234 * 10 = 2.34
.34 * 10 = 3.4
.4 * 10 = 4.0
Problems will however occur when you have a number that is "floating" like 1.199999999.
int numFloating = 0;
double orgin = 1.251564;
double value = orgin - floor(orgin);
while(value == 0)
{
value *= 10;
value = value - floor(value);
numFloating ++;
}
By using this code sometimes answer is wrong. exp: zero in floating point is equal to (2^31)-1.
Obviously output depends on how it realy stored.
I'm having trouble doing what I think should be a fairly simple task in C++. I'm trying to output a floating point value to be written into a log file. The log file has 7 characters designated for the number output, but I'm finding it to be a little nontrivial to get a constant 7 character output over a wide range of values of different magnitudes, signs, and precisions (eg: 1, -0.60937, 0.60937, 0.009371, -0.009371). I've got a somewhat hacked way to kinda do it:
int desiredPrecision = 6;
if (runningAvg < 0)
desiredPrecision--;
if (std::abs((long) runningAvg) < 1)
desiredPrecision--;
else
theFile << std::showpoint;
theFile.precision (desiredPrecision);
theFile.fill('0');
theFile.setf(std::ios_base::left, std::ios_base::adjustfield);
theFile.width(7);
theFile << runningAvg << std::endl;
But this way seems extremely hacky to me. It works with numbers like:
-0.60937 (outputs: -0.6094)
-1.7 (-1.7000)
-1 (-1.0000)
0.6937 (0.60937)
0.00937 (0.00937)
but it breaks with
0.009371 (0.009371)
and
-0.009371 (-0.009371)
Now, I could add another level of if-else statements to deal with small magnitude numbers, but that just seems to be adding to the level of hackiness, and not a clean way to do it. I've played a bit with fprintf, but it seems like it is more concerned with a strict mathematical definition of precision, whereas in this application I care more about restricting the width of the field to 7 characters at all times. (I can also rely on these numbers never being so large that I'll overflow 6 characters plus a sign)
Am I missing something obvious here? Anyone have any tips for a less hacked way to achieve this?
Don't know how to do this with iostream stuff but I think that the ?printf format string you're looking for is one of these:
%.4f for negative numbers and %07.5f for positive numbers.
%+.4f (positive numbers will have a leading +)
% .4f (positive numbers will have a leading space)
The easiest way to do it is to print into a string and chop the string.
You are really doing text processing/report generation not floating point number handling sop treat it as a formatting problem
If you are not concern with precision (or concern enough to use the same precision for all numbers) you could use the same "%7.0e" format for all numbers.
Example
#include <stdio.h>
static const char* format = "%7.0e";
int main() {
double a[] = {1, -0.60937, 0.60937, 0.009371, -0.009371,
-1, -1.2e8, 1e-4, 1e-5, -1.5e-321, 0/.0, 1/0.};
for (unsigned i = 0; i < sizeof(a) / sizeof(*a); ++i) {
printf(format, a[i]);
puts("");
if (snprintf(0,0, format, a[i]) != 7)
return 1;
}
}
Output
1e+00
-6e-01
6e-01
9e-03
-9e-03
-1e+00
-1e+08
1e-04
1e-05
-2e-321
nan
inf
Is there a way to print in scientific notation less than 3 places for exponent part of number?
The 6.1 formatting doesn't affect exponent but only the number part:
var=1.23e-9;
printf ("%e\n", var);
printf ("%6.1e\n", var);
gives
1.230000e-009
1.2e-009
I've also tried this in wxWidgets with formatting of string but the behavior is the same.
m_var->SetLabel(wxString::Format(wxT("%6.1e"),var));
What I'd like to have is 1.2e-9.
According to Wikipedia:
The exponent always contains at least two digits; if the value is
zero, the exponent is 00. In Windows, the exponent contains three
digits by default, e.g. 1.5e002, but this can be altered by
Microsoft-specific _set_output_format function.
_set_output_format
I've had to do this a lot (I write file parsers and some file formats like NITF require you to store numeric values as strings).
What you do is an exploit based on what base-10 math (scientific notation) really means: It means that for all real numbers y, y = (x) * 10^(N) for some integer N and some x in the range (-1, 1) exclusive.
So, you do the following
void PrintScientific(double d)
{
int exponent = (int)floor(log10( fabs(d))); // This will round down the exponent
double base = d * pow(10, -1.0*exponent);
printf("%lfE%+01d", base, exponent);
}
You can add all the format specifiers you need to control the # of chars before, after the "." decimal place.
Do NOT forget the rounding step! This is how it works, using the properties of base10 and logarithms (base 10 here):
Let y = x * 10^N =>
log(y) = log(x*10^N) =>
log(y) = log(x) + log(10^N) => // From Log "product" rule
log(y) = log(x) + N
Since x is in the range (-10, 10) -"()" means exclusive(exclusive), that implies log(x) is in the range (-1, 1). So when we round down for integer conversion, we're dropping "log(x)" contribution.
You can then get the "x" portion from the original number, which lets you output the original in any scientific notation you want to use.
With standard C printf() this can't be done (and the use of three digits by default seems wrong as well), at least in C99 (I don't have a newer version at hand). The relevant quote from the C99 standard is at 7.19.6.1 paragraph 8, formats e,f:
.... The exponent always contains at least two digits, and only as many more digits as necessary to represent the exponent. If the value is zero, the exponent is zero. ...
The best bet to fit this [portably] into code using lots of these outputs is to use C++ IOStreams: although the default formatting is the same as in C, it is possible to install a custom facet into the stream's std::locale which does the formatting the way you need. That said, writing the formatting code might not be entirely trivial. Although I would probably just built on the standard conversion and then remove the excess zeros after the e character.
I found Zach's answer to be the fastest and simplest method and is also applicable to any OS. I did find that two modifications were needed on the "base =" line for it to work for all numbers. (Otherwise nan's when exponent is negative in cygwin). The extra print statement is just for patran neutral file compatibility. I would have upvoted his answer, but I just started on stackexchange so I don't have sufficient "reputation".
void PrintScientific(double d)
{
int exponent = (int)floor(log10( fabs(d))); // This will round down the exponent
double base = (d * pow(10.0, -1*exponent));
if(abs(exponent)<10)
printf("%13.9lfE%+01d", base, exponent);
else
printf("%12.9lfE%+01d", base, exponent);
}
C/C++ specifies at least two exponent digits with printf("%e",...). To print only 1, and to deal with Visual Studio which, by default, prints at least 3, additional code is needed.
Consider IOStreams #Dietmar Kühl
If C++ code still wants to use printf() style formats:
Adjusting the value of a double before calling printf() too often results in rounding issues, range shorting and general corner case failures like dealing with log10(0.0). Also consider large double just near a power-of-10 where log10() may come up short, -0.0, INF, NAN.
In this case, better to post-process the string.
double var = 1.23e-9;
// - 1 . x e - EEEEE \0
#define ExpectedSize (1+1+1+1+1+1+ 5 + 1)
char buf[ExpectedSize + 10];
snprintf(buf, sizeof buf, "%.1e", var);
char *e = strchr(buf, 'e'); // lucky 'e' not in "Infinity" nor "NaN"
if (e) {
e++;
int expo = atoi(e);
snprintf(e, sizeof buf - (e - buf), "%1d", expo);
}
printf("'%6s'\n", buf); // '1.2e-9'
Note: %e is amiable to post-processing as its width is not so unwieldy as "%f". sprintf(buf, "%f", DBL_MAX) could be 1000s of char.
Lets consider we have a double R = 99.999999; (which may be obtained by a result of some other computation),now the desired output is 99.99
I tried using printf("%.2lf",R); but it's rounding off the value.How to get the desired output ? (preferably using printf)
#include <math.h>
...
printf("%.2f", floor(100 * R) / 100);
All you have to do is subtract .005 from the number and magically printf will behave as you wish: always round down.
sprintf it into a buffer, and then put the NUL char two bytes past the '.'
Then printf your final string using the intermediate one.
If you have it, use fmod() to chop the tail of the double:
double rounded = R - fmod(R, 0.01);
// Now just print rounded with what you were using before
This has the advantage of working the same if R is positive or negative.
What about using double trunc(double) from GLibC?
Can you multiply by 100 and then truncate to an integer? Then you could format the result like one would with dollars and cents. Simply dividing by 100 might land you back at square one due to floating-point representation issues.
Another solution, using casts:
...
printf("%.2lf", (double) ((int) (R * 100)) / 100);
Another way, truly sign agnostic:
printf("%d.%d\n", (int) r ,abs((int)(r*100) % 100));
How to convert string (22.123) format number into float variable format without using any API in c++. This is just to understand more about the inside coding.. thnx
something like:
double string_to_double(std::string s)
{
int p = 0;
int p_dec = s.length();
double val = 0;
for (int i=0; i<s.length(); ++i)
{
double digit = (double)(s[i] - '0');
if (s[i] == '.') { p_dec = p; }
else { val += digit*powf(10,p--); }
}
val /= powf(10, p_dec);
}
Basic algorithm, assuming no input in the form 1.2e-4:
(1) Read an integer before the dot. If the number of digits is > 16 (normal precision of double), convert that integer into floating point directly and return.
(2) Read an at most 16 digits dot as an integer. Compute (that integer) ÷ 10digits read. Sum up this with the integer in step (1) and return.
This only involve 2 floating point operation: one + and one ÷, and a bunch of integer arithmetics. The advantage over multiplications and divisions by powers of 10 is that the error won't accumulate unnecessarily.
(To read 16-digit integers you need a 64-bit int.)
In reality, you should use sscanf(str, "%lf", ...), std::istringstream, or boost::lexical_cast<double>.
go over the number digit by digit by using a bunch of multiplications and divisions by powers of 10 and construct the string character by character.
If you just want an idea of how to do it, the other answer, if you want an accurate result, the problem is not so simple and you should refer to the literature on the subject. An example: ftp://ftp.ccs.neu.edu/pub/people/will/howtoread.ps
I'm pretty sure that the Plauger Standard C Library book has a disc with the source of strtod.
http://www.amazon.co.uk/Standard-C-Library-P-J-Plauger/dp/0131315099
and there are online versions too:
http://www.google.co.uk/search?hl=en&client=firefox-a&hs=IvI&rls=org.mozilla%3Aen-GB%3Aofficial&q=strtod+source+code