Floating-point precision issues, or a broken printf?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Floating-point precision issues, or a broken printf?

Post by 01000101 »

hey, I recently ported most of (all but the file-system functions) PDPCLib v1.00. From there, I decided to write floating-point support into my printf() [%f]. I seem to have most of it complete, but I'm having some precision problems. I set the FPU control word (verified by bochs debugger) to 80-bit precision and rounding-up.

In Linux, when I use printf("%1.22f\n", (double)0.12345678901234567890) I get about 17 decimal places worth of precision, on mine I get about 7 decimal places of precision. I typecast on both Linux and my OS to (double) to ensure that one isn't using "float" or "long double".

Here's my code for printing the float (and compensate for 2 digits worth of rounding), it's a mish-mash of different OSS/PD code.

Code: Select all

static void print_double(double d, size_t precision) 
{
	double di, df, pr, tmp;
   
	/* if it's zero, just print the '0' and exit */
	if(d == 0.0)
	{ print_char('0'); return; }
	/* if it's a negative integer, print '-' and make the integer absolute */
	else if (d < 0) 
	{
		print_char('-');
		d = fabs(d);
	}
   
	/* break the double into fraction (df) and integer (di) parts */
	df = modf(d, &di);

	/* print the integer portion */
	print_int((size_t)floor(di));

	/* round up if necessary */
	if (df != 0) 
	{ 
		print_char('.');

		pr = df * pow(10, precision+1);
		modf(pr, &pr);
		
		/* we need to extract the last+1 decimal place and see if we should round up */
		while(pr > 10.0){ pr /= 10; }
		/* if it's 4, we should check the next decimal place to see if it's >= 5 */
		if(pr == 4)
		{
			pr = df * pow(10, precision+2);
			modf(pr, &pr);
			while(pr > 10.0){ pr /= 10; }
			if(pr >= 5){ df = df + (0.1 / pow(10, precision)); }
		}
		if(pr >= 5){ df = df + (0.1 / pow(10, precision)); }
	}

	/* calculate the fractional portion to print */
	while (df != 0 && precision--) 
	{
		df = df * 10;
		df = modf(df, &di);

		print_int((int)di);
	}
}
I've tested it with and without the rounding, so I doubt that is the issue (although it is very experimental). I would hope it would not be the floor() or modf() functions as they are part of the PDPCLib.

Any ideas?
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: Floating-point precision issues, or a broken printf?

Post by bewing »

Well, since nobody else seems to be replying to this, I guess I will say one little thing. I've looked at the code a little, and it seems OK. However, getting 7 significant digits on a supposedly double-precision equation is almost always a sign that one of the operands has only been calculated as a single-precision float. As far as I can tell, all the function calls you made should return good doubles. However, I'm going to bet that within one of those functions, some variable or function call is only a float. So, yes, I'm figuring the error is in the library. If you have any opportunity, this is exactly the kind of error that singlestepping through the code (including the library sourcecode) will locate quickly.
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: Floating-point precision issues, or a broken printf?

Post by 01000101 »

Thanks for replying.

I haven't got around to single-stepping through the library calls (it's on the ToDo list), but I'm starting to trust this library less and less the more I look into it. I recently found out that the log() function gets stuck in an endless while loop (and I don't have the mathematical expertise to figure out why). I'll probably end up ditching this library (PDPClib) in favor of a more well-known/tested library (uClibc probably).

I'll report back once I get around to debugging the function calls.
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: Floating-point precision issues, or a broken printf?

Post by bewing »

Doesn't Solar's C library have all this stuff in it?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Floating-point precision issues, or a broken printf?

Post by Combuster »

Floating point stuff is pretty much absent. There's no math.h (there is in my edited version) and *printf doesn't have floating point support.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: Floating-point precision issues, or a broken printf?

Post by 01000101 »

bewing wrote:Doesn't Solar's C library have all this stuff in it?
unfortunately not.
Combuster wrote:Floating point stuff is pretty much absent. There's no math.h (there is in my edited version) and *printf doesn't have floating point support.
There's a lot of integrated mathematical functions that need to be written for even the most basic of %f/g format support.

I'm currently trying to get uClibc setup with my OS, but it's not going well. It has a very nice set of math functions that I'd like to be able to use.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Floating-point precision issues, or a broken printf?

Post by Solar »

bewing wrote:Doesn't Solar's C library have all this stuff in it?
Erm... nope. :oops:

It took me about a year to churn out Freestanding, <string.h> and <stdlib.h>, and I was quite confident I could continue at that rate.

Then I screwed up my first attempt at <stdio.h>, got two kids, played WoW more than was good for me (and my family), and eventually, inherited a house that was in dire need of a complete overhaul which we are still in the aftermath of.

I.e., no I/O, no locale, wide char, time, or math support in PDCLib, yet.

I am (again) hoping for the Breakpoint weekend (Easter, you heathens!), to re-ignite my productivity. And I am so fed up with being stuck in <stdio.h> for three years that I am willing to take two weeks of vacation afterwards just to get this &$%&§ thing done. :evil:
Every good solution is obvious once you've found it.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Floating-point precision issues, or a broken printf?

Post by Combuster »

wide char
I implemented a bunch of that since I needed it for the freebasic runtime, if you want to have it... (my server's down atm, so I'll mail it if you want it)
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Floating-point precision issues, or a broken printf?

Post by Solar »

None of the stuff is missing because I can't do it, it's missing because a) it's reserved for a later step (do one thing at a time) and b) I didn't have the time to get to that step yet.

But thanks for the offer.
Every good solution is obvious once you've found it.
Post Reply