Personal computing discussed

Moderators: renee, SecretSquirrel, just brew it!

 
paco
Minister of Gerbil Affairs
Topic Author
Posts: 2083
Joined: Wed Jul 21, 2004 7:14 pm
Location: So Cal

C++ decimal rounding

Wed Dec 07, 2005 10:07 pm

hey is there an easy way to make the decimals round off?

like 34.2353 gets put out as 34.24?

I know there is setprecision but that does the whole number

right now i have: int(cst)<<'.'<<int((cst-int(cst))*100+.5)
cst is a float variable.
 
IntelMole
Grand Gerbil Poohbah
Posts: 3506
Joined: Sat Dec 29, 2001 7:00 pm
Location: The nearest pub
Contact:

Thu Dec 08, 2005 3:59 pm

My old physics coursemates did a problem in C similar to this. Numerically find the integral of e[-(x^2)] (between 1 and 10), and state it to a precision determined at runtime, using a number of steps .

The basis of the rounding was to multiply the number by 10 to the power of (however many sig figs you need), remove the fractional part using an integer cast, cast it back to floating point, and divide back again by 10^(sig figs). The integrate function has been excluded because it's just not neccessary. And the while loop is there simply to keep performing the calculation until the step size is significantly small enough to obtain this accuracy.

#include <stdio.h>
#include <math.h>

main()
{
double sf;
double ans1, ans2, ans;
int est1, est2;
double steps = 10.0;
printf("\nHow many significant figures accuracy is required?\n");
scanf("%lf", &sf);

ans1 = integrate  (steps);
est1 = (int)(ans1 * pow(10.0,sf));
printf("est1 = %d\n", est1);

steps = steps * 10;

ans2 = integrate(steps);
est2 = (int)(ans2 * pow(10.0,sf));
printf("est2 = %d\n\n", est2);

while(est1 != est2)
{
     est1 = est2;
     printf("est1 = %d\n", est1);

     steps = steps * 10;

     ans2 = integrate(steps);
     est2 = (int)(ans2 * pow(10.0,sf));
     printf("est2 = %d\n\n", est2);
}

ans2 = (double) est2;
ans = (ans2)/pow(10.0,sf);

printf("The answer is % .9lf\n",ans);
}


It should also be noted that this only works for up to 9 significant figures of precision for some reason. We speculated that this was due to either the variable resolution of the double precision floating point system, or because 10^10 is simply a pretty big number and was causing some sort of arithmetic overflow error. But we never thought of a better way to do this. Hence the
% .9lf
in the code.

I have little to zero knowledge of c++, so this may or may not be applicable to what you're trying to do :-D,
-Mole
Living proof of John Gabriel's theorem
 
Craig P.
Gerbil Team Leader
Posts: 285
Joined: Tue Dec 31, 2002 3:12 am
Location: South Bend, IN

Thu Dec 08, 2005 5:42 pm

The guts of it should be applicable to C++ too -- the places where C++ really significantly diverges from C are containers, strings, and I/O.
 
Foolio
Gerbil
Posts: 81
Joined: Mon Jan 12, 2004 1:00 am
Location: Canada

Thu Dec 08, 2005 5:53 pm

IntelMole wrote:
It should also be noted that this only works for up to 9 significant figures of precision for some reason. We speculated that this was due to either the variable resolution of the double precision floating point system, or because 10^10 is simply a pretty big number and was causing some sort of arithmetic overflow error. But we never thought of a better way to do this. Hence the
% .9lf
in the code.



Have you tried using long variables instead of integer variables?
Athlon64 X2 3800+ @ 2.5 | DFI Ultra-D | 2GB OCZ GX XTC 4000 | Radeon X800XL @ 450/590 | 74GB Raptor
 
bitvector
Grand Gerbil Poohbah
Posts: 3293
Joined: Wed Jun 22, 2005 4:39 pm
Location: San Francisco, CA

Thu Dec 08, 2005 6:21 pm

Foolio wrote:
Have you tried using long variables instead of integer variables?

On the most common 32-bit platforms, a long int is going to be the same width as an unqualified int.
 
IntelMole
Grand Gerbil Poohbah
Posts: 3506
Joined: Sat Dec 29, 2001 7:00 pm
Location: The nearest pub
Contact:

Thu Dec 08, 2005 6:59 pm

Just tried recompiling the code. The correct answer, to 9 sig figs, is:
0.8862269250

Using long ints give the exact same response as before at 10 sig figs:
-0.2147483648

Using unsigned ints gives a different, but still incorrect answer, suggesting that even this is insufficient range for the operation (since you're only increasing that by a factor of 2, yet you're increasing the number by a factor of 10):
0.0272334662

But as long as 9 sig figs is sufficient for the OP's problem, this is all little more than bug finding :-D,
-Mole
Living proof of John Gabriel's theorem
 
just brew it!
Administrator
Posts: 54500
Joined: Tue Aug 20, 2002 10:51 pm
Location: Somewhere, having a beer

Thu Dec 08, 2005 7:08 pm

bitvector wrote:
Foolio wrote:
Have you tried using long variables instead of integer variables?

On the most common 32-bit platforms, a long int is going to be the same width as an unqualified int.

Many 32-bit compilers do support a 64-bit integer type long long (or __int64 in MS-speak).
Nostalgia isn't what it used to be.
 
IntelMole
Grand Gerbil Poohbah
Posts: 3506
Joined: Sat Dec 29, 2001 7:00 pm
Location: The nearest pub
Contact:

Thu Dec 08, 2005 7:17 pm

Ding Ding Ding! We have a winner.

My computer's currently sitting here looking at 15 sig fig accuracy :-D,
-Mole

edit: it's sat here pondering this result for about 4 minutes now, which is not right. I'd say it's broken :-D
Living proof of John Gabriel's theorem
 
IntelMole
Grand Gerbil Poohbah
Posts: 3506
Joined: Sat Dec 29, 2001 7:00 pm
Location: The nearest pub
Contact:

Thu Dec 08, 2005 7:43 pm

OK, so I left it for a bit, to see what it would do.

After 20 minutes CPU time according to windows explorer, I gave up the ghost. I'd guess that the resolution of a double precision floating point gave up on it at that step size.
-Mole
Living proof of John Gabriel's theorem
 
bitvector
Grand Gerbil Poohbah
Posts: 3293
Joined: Wed Jun 22, 2005 4:39 pm
Location: San Francisco, CA

Thu Dec 08, 2005 8:18 pm

just brew it! wrote:
bitvector wrote:
Foolio wrote:
Have you tried using long variables instead of integer variables?

On the most common 32-bit platforms, a long int is going to be the same width as an unqualified int.

Many 32-bit compilers do support a 64-bit integer type long long (or __int64 in MS-speak).

Yes, but I hesitated to recommend long long since it's a C99 feature that is not in ISO C++98 and the OP was using C++. Use of a long long will likely cause the compiler to drop a warning on your ass.
 
just brew it!
Administrator
Posts: 54500
Joined: Tue Aug 20, 2002 10:51 pm
Location: Somewhere, having a beer

Thu Dec 08, 2005 8:32 pm

bitvector wrote:
Use of a long long will likely cause the compiler to drop a warning on your ass.

I've never had a warning "dropped on my ass" before. Does it hurt? :lol:
Nostalgia isn't what it used to be.
 
Flying Fox
Gerbil God
Posts: 25690
Joined: Mon May 24, 2004 2:19 am
Contact:

Thu Dec 08, 2005 11:03 pm

I just wonder how many new folding boxen we are going to demand for our services this time. :P
 
Craig P.
Gerbil Team Leader
Posts: 285
Joined: Tue Dec 31, 2002 3:12 am
Location: South Bend, IN

Fri Dec 09, 2005 2:22 am

IntelMole wrote:
Ding Ding Ding! We have a winner.

My computer's currently sitting here looking at 15 sig fig accuracy :-D,
-Mole

edit: it's sat here pondering this result for about 4 minutes now, which is not right. I'd say it's broken :-D

Doubles carry about 15 digits of precision, as I recall.
 
thegleek
Darth Gerbil
Posts: 7460
Joined: Tue Jun 10, 2003 11:06 am
Location: Detroit, MI
Contact:

Fri Dec 09, 2005 11:02 am

straight from my The C Programming Langauge book by Brian Kernighan & Dennis Ritchie:

using the printf command:

%d    print as decimal integer
%6d   print as decimal integer, at least 6 characters wide
%f    print as floating point
%6f   print as floating point, at least 6 characters wide
%.2f  print as floating point, 2 characters wide AFTER decimal point
%6.2f print as floating point, at least 6 characters wide and 2 AFTER decimal point


ie:
#include <stdio.h>

/* print Fahrenheit-Celsius table */

main()
{
     int fahr;

     for (fahr = 0; fahr <= 300; fahr = fahr + 20)
          printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
}


The output looks like this:
 0  -17.8
20   -6.7
40    4.4

...
––•–√\/––√\/––•–– nostalgia is an emotion for people with no future ––•–√\/––√\/––•–-
 
Flying Fox
Gerbil God
Posts: 25690
Joined: Mon May 24, 2004 2:19 am
Contact:

Fri Dec 09, 2005 12:27 pm

I don't think the printf precision does rounding.
 
just brew it!
Administrator
Posts: 54500
Joined: Tue Aug 20, 2002 10:51 pm
Location: Somewhere, having a beer

Fri Dec 09, 2005 1:09 pm

Flying Fox wrote:
I don't think the printf precision does rounding.

Actually, it does.

But I was under the impression that the original poster wanted the rounded value to be stored in a (numeric) variable for subsequent use. Reading back through this thread, I'm not sure why I thought that.
Nostalgia isn't what it used to be.
 
notfred
Maximum Gerbil
Posts: 4610
Joined: Tue Aug 10, 2004 10:10 am
Location: Ottawa, Canada

Fri Dec 09, 2005 1:40 pm

sprintf if you need it internally.
 
just brew it!
Administrator
Posts: 54500
Joined: Tue Aug 20, 2002 10:51 pm
Location: Somewhere, having a beer

Fri Dec 09, 2005 1:51 pm

notfred wrote:
sprintf if you need it internally.

...as long as you don't intend to do any calculation with the result. I suppose you could always do a strtod to convert back to floating point.
Nostalgia isn't what it used to be.
 
paco
Minister of Gerbil Affairs
Topic Author
Posts: 2083
Joined: Wed Jul 21, 2004 7:14 pm
Location: So Cal

Fri Dec 09, 2005 1:58 pm

oops ya i only wanted it for output not for calculations, sorry my first post was rushed since my battery was almost dead ;), but can i use print f in c++?
 
just brew it!
Administrator
Posts: 54500
Joined: Tue Aug 20, 2002 10:51 pm
Location: Somewhere, having a beer

Fri Dec 09, 2005 2:02 pm

paco wrote:
oops ya i only wanted it for output not for calculations, sorry my first post was rushed since my battery was almost dead ;),

Actually the post was OK... I just misunderstood. :oops:

paco wrote:
can i use print f in c++?

Yes. Just include stdio.h (like you would in a C program).
Nostalgia isn't what it used to be.
 
Shining Arcanine
Gerbil Jedi
Posts: 1718
Joined: Wed Jun 11, 2003 11:30 am

Re: C++ decimal rounding

Fri Dec 09, 2005 2:05 pm

paco wrote:
hey is there an easy way to make the decimals round off?

like 34.2353 gets put out as 34.24?

I know there is setprecision but that does the whole number

right now i have: int(cst)<<'.'<<int((cst-int(cst))*100+.5)
cst is a float variable.


Are you using C++ .NET?
 
paco
Minister of Gerbil Affairs
Topic Author
Posts: 2083
Joined: Wed Jul 21, 2004 7:14 pm
Location: So Cal

Re: C++ decimal rounding

Fri Dec 09, 2005 5:52 pm

Shining Arcanine wrote:
Are you using C++ .NET?


no i'm using g++ on a linux machine

and jbi, I'm not too familar with C just C++.
 
liquidsquid
Minister of Gerbil Affairs
Posts: 2661
Joined: Wed May 29, 2002 10:49 am
Location: New York
Contact:

Sat Dec 10, 2005 10:15 am

just brew it! wrote:
Flying Fox wrote:
I don't think the printf precision does rounding.

Actually, it does.

But I was under the impression that the original poster wanted the rounded value to be stored in a (numeric) variable for subsequent use. Reading back through this thread, I'm not sure why I thought that.


I believe rouding is not specified under ANSI for it, so depending on the comipler it may or may not round. You have to be careful! However with that said, I have not come across a compiler yet this did not round by the format specifiers except on very small uC devices where space is critical (<2K of memory).
 
bitvector
Grand Gerbil Poohbah
Posts: 3293
Joined: Wed Jun 22, 2005 4:39 pm
Location: San Francisco, CA

Sat Dec 10, 2005 6:41 pm

liquidsquid wrote:
I believe rouding is not specified under ANSI for it, so depending on the comipler it may or may not round. You have to be careful! However with that said, I have not come across a compiler yet this did not round by the format specifiers except on very small uC devices where space is critical (<2K of memory).

The C99 standard says that "the result should be correctly rounded" as part of the "recommended practice" subsection of fprintf. I guess this means it's suggested but not strictly necessary. And the issue you cite above is not dependent on the compiler but rather the C runtime library's implementation of fprintf.
 
seeker010
Gerbil First Class
Posts: 143
Joined: Sat Oct 19, 2002 8:52 am

Re: C++ decimal rounding

Sat Dec 10, 2005 7:10 pm

paco wrote:
hey is there an easy way to make the decimals round off?

like 34.2353 gets put out as 34.24?

I know there is setprecision but that does the whole number

right now i have: int(cst)<<'.'<<int((cst-int(cst))*100+.5)
cst is a float variable.

cout<<setprecision(numOfPlaces+1)<<cst<<endl;
(actually this is compiler specific)

e.g.
#include <iostream>
#include <iomanip>

using std::cout;
using std::setprecision;
using std::endl;

int main(void){
        double a=3.1415;
        cout<<setprecision(4)<<a<<endl;
        return 0;
}

./a.out
3.142

if you want to round it, and then be able to use it again:
#include <iostream>
#include <iomanip>
#include <sstream>
#include <cstdlib>

using std::string;
using std::cout;
using std::setprecision;
using std::endl;
using std::ostringstream;

int main(void){
        double a=3.1415;
        ostringstream ossout;
        string temp;
        ossout<<setprecision(4)<<a<<endl;
        temp=ossout.str();
        a=strtod(temp.c_str(),NULL);
        cout<<setprecision(9)<<a<<endl;
        return 0;
}

[lidq@localhost ~]$ g++ prec2.cxx
[lidq@localhost ~]$ ./a.out
3.142
 
Craig P.
Gerbil Team Leader
Posts: 285
Joined: Tue Dec 31, 2002 3:12 am
Location: South Bend, IN

Sun Dec 11, 2005 5:09 pm

paco wrote:
oops ya i only wanted it for output not for calculations, sorry my first post was rushed since my battery was almost dead ;), but can i use print f in c++?


You can. In many cases, though, the iostreams will be more convenient to use.
 
Craig P.
Gerbil Team Leader
Posts: 285
Joined: Tue Dec 31, 2002 3:12 am
Location: South Bend, IN

Sun Dec 11, 2005 5:11 pm

bitvector wrote:
liquidsquid wrote:
I believe rouding is not specified under ANSI for it, so depending on the comipler it may or may not round. You have to be careful! However with that said, I have not come across a compiler yet this did not round by the format specifiers except on very small uC devices where space is critical (<2K of memory).

The C99 standard says that "the result should be correctly rounded" as part of the "recommended practice" subsection of fprintf. I guess this means it's suggested but not strictly necessary. And the issue you cite above is not dependent on the compiler but rather the C runtime library's implementation of fprintf.


That would make it a quality-of-implementation issue -- but one significant enough that I can't imagine it wouldn't be a priority for any compiler developer.
 
bitvector
Grand Gerbil Poohbah
Posts: 3293
Joined: Wed Jun 22, 2005 4:39 pm
Location: San Francisco, CA

Sun Dec 11, 2005 5:38 pm

Craig P. wrote:
bitvector wrote:
The C99 standard says that "the result should be correctly rounded" as part of the "recommended practice" subsection of fprintf. I guess this means it's suggested but not strictly necessary. And the issue you cite above is not dependent on the compiler but rather the C runtime library's implementation of fprintf.

That would make it a quality-of-implementation issue -- but one significant enough that I can't imagine it wouldn't be a priority for any compiler developer.

Uh, again... as I pointed out in my post this issues has nothing to do with the actual compiler developers. Sometimes the compiler and library developers are the same people, but not always. I mean, gcc is used on targets with a wide variety C runtime libraries. If you file a bug report on gcc because fprintf on uClibc or Sun's libc doesn't round correctly, you're yelling at the wrong people.
 
liquidsquid
Minister of Gerbil Affairs
Posts: 2661
Joined: Wed May 29, 2002 10:49 am
Location: New York
Contact:

Mon Dec 12, 2005 1:44 pm

bitvector wrote:
Uh, again... as I pointed out in my post this issues has nothing to do with the actual compiler developers. Sometimes the compiler and library developers are the same people, but not always. I mean, gcc is used on targets with a wide variety C runtime libraries. If you file a bug report on gcc because fprintf on uClibc or Sun's libc doesn't round correctly, you're yelling at the wrong people.


Point taken. In my line of work, they are usually one in the same since the chip-maker also provides the tools. I think of a compiler as the entire development package, even though that is not correct. Should be IDE...

In my line of work as well... a lot of shortcuts are taken in the libraries to save space, and the granularity is fairly high. A lot of features are "switchable" and they frequently bite you in the butt when you forget to enable a feature.
-LS
 
Craig P.
Gerbil Team Leader
Posts: 285
Joined: Tue Dec 31, 2002 3:12 am
Location: South Bend, IN

Wed Dec 14, 2005 3:19 am

bitvector wrote:
Craig P. wrote:
bitvector wrote:
The C99 standard says that "the result should be correctly rounded" as part of the "recommended practice" subsection of fprintf. I guess this means it's suggested but not strictly necessary. And the issue you cite above is not dependent on the compiler but rather the C runtime library's implementation of fprintf.

That would make it a quality-of-implementation issue -- but one significant enough that I can't imagine it wouldn't be a priority for any compiler developer.

Uh, again... as I pointed out in my post this issues has nothing to do with the actual compiler developers. Sometimes the compiler and library developers are the same people, but not always. I mean, gcc is used on targets with a wide variety C runtime libraries. If you file a bug report on gcc because fprintf on uClibc or Sun's libc doesn't round correctly, you're yelling at the wrong people.


Well, it's part of the compiler platform (if not the compiler specifically), but presumably if you're using the platform, you know who you should be yelling at.

Who is online

Users browsing this forum: No registered users and 1 guest
GZIP: On