[HACKERS] somebody could explain this?
Hello, I'm using PostgreSQL 8.0.4 in Fedora Core 3, right now I'm learning a little about the postgresql internals and the way some kind of SPs could be written in c language; I found something really weird and I cannot explain to me this behavior: #include postgres.h #include fmgr.h PG_FUNCTION_INFO_V1(test); Datum repeat_item(PG_FUNCTION_ARGS) { int num_times; num_times = PG_GETARG_FLOAT8(0) * 100; PG_RETURN_INT32(num_times); } Inside psql this happens: # Create or replace function test(float) returns integer as 'test.so' language 'c' stable; select test(0.1); Returns 10 Select test(0.11); Returns 11 Select test(0.12) Returns 11 Select test(0.13) Returns 13 Select test(0.14) Returns 14 Select test(0.15) Returns 14 What Is happening here? ---(end of broadcast)--- TIP 9: In versions below 8.0, the planner will ignore your desire to choose an index scan if your joining column's datatypes do not match
Re: [HACKERS] somebody could explain this?
Classic behaviour, which has nothing to do with postgres. Try the program below to see the same effect. You probably should be using a rounding function to see what you seem to expect. cheers andrew #include stdio.h main() { double x[] = { 0.1, 0.11, 0.12, 0.13, 0.14, 0.15 }; int i,n; for (i=0 ; i 6; i++) { n = x[i] * 100; printf(%d\n,n); } } Cristian Prieto wrote: Hello, I'm using PostgreSQL 8.0.4 in Fedora Core 3, right now I'm learning a little about the postgresql internals and the way some kind of SPs could be written in c language; I found something really weird and I cannot explain to me this behavior: #include postgres.h #include fmgr.h PG_FUNCTION_INFO_V1(test); Datum repeat_item(PG_FUNCTION_ARGS) { int num_times; num_times = PG_GETARG_FLOAT8(0) * 100; PG_RETURN_INT32(num_times); } Inside psql this happens: # Create or replace function test(float) returns integer as 'test.so' language 'c' stable; select test(0.1); Returns 10 Select test(0.11); Returns 11 Select test(0.12) Returns 11 Select test(0.13) Returns 13 Select test(0.14) Returns 14 Select test(0.15) Returns 14 What Is happening here? ---(end of broadcast)--- TIP 9: In versions below 8.0, the planner will ignore your desire to choose an index scan if your joining column's datatypes do not match ---(end of broadcast)--- TIP 4: Have you searched our list archives? http://archives.postgresql.org
Re: [HACKERS] somebody could explain this?
On Fri, Nov 04, 2005 at 10:16:50AM -0600, Cristian Prieto wrote: Hello, I'm using PostgreSQL 8.0.4 in Fedora Core 3, right now I'm learning a little about the postgresql internals and the way some kind of SPs could be written in c language; I found something really weird and I cannot explain to me this behavior: What's happening here is that the multiplication, being floating point, has some accumulated error such that when you multiply it by 100 and convert it to an int, it hits the cutoff. Note: converting a float to an int tends to invoke trunc() or something similar. trunc(14.) = 14. You need to decide whether maybe you want round() instead. Or decide the actual cutoff yourself. I sometimes fix this by adding 0.1 to numbers before converting to integer, to avoid these issues. Floating points numbers are accurate but not precise. Hope this helps, -- Martijn van Oosterhout kleptog@svana.org http://svana.org/kleptog/ Patent. n. Genius is 5% inspiration and 95% perspiration. A patent is a tool for doing 5% of the work and then sitting around waiting for someone else to do the other 95% so you can sue them. pgpkJMD5sNVGk.pgp Description: PGP signature
Re: [HACKERS] somebody could explain this?
Cristian Prieto [EMAIL PROTECTED] writes: Datum repeat_item(PG_FUNCTION_ARGS) { int num_times; num_times = PG_GETARG_FLOAT8(0) * 100; PG_RETURN_INT32(num_times); } # Create or replace function test(float) returns integer as 'test.so' language 'c' stable; float is FLOAT4 not FLOAT8 ... your function is picking up some garbage data. There might also be some roundoff issues to think about --- I'd be inclined to add an rint() call, or at least add 0.5 before truncating to integer. regards, tom lane ---(end of broadcast)--- TIP 3: Have you checked our extensive FAQ? http://www.postgresql.org/docs/faq
Re: [HACKERS] somebody could explain this?
Cristian, I bet it's related to some rounding issue and the fact that floating formats are approximative even for small integers. Probably 12 ands up being slightly less in floating format (something like 11.999...), and the cast to integer is truncating it. Not 100% sure though... read up on your API, I'm not a C programmer :-) HTH, Csaba. On Fri, 2005-11-04 at 17:16, Cristian Prieto wrote: Hello, I'm using PostgreSQL 8.0.4 in Fedora Core 3, right now I'm learning a little about the postgresql internals and the way some kind of SPs could be written in c language; I found something really weird and I cannot explain to me this behavior: #include postgres.h #include fmgr.h PG_FUNCTION_INFO_V1(test); Datum repeat_item(PG_FUNCTION_ARGS) { int num_times; num_times = PG_GETARG_FLOAT8(0) * 100; PG_RETURN_INT32(num_times); } Inside psql this happens: # Create or replace function test(float) returns integer as 'test.so' language 'c' stable; select test(0.1); Returns 10 Select test(0.11); Returns 11 Select test(0.12) Returns 11 Select test(0.13) Returns 13 Select test(0.14) Returns 14 Select test(0.15) Returns 14 What Is happening here? ---(end of broadcast)--- TIP 9: In versions below 8.0, the planner will ignore your desire to choose an index scan if your joining column's datatypes do not match ---(end of broadcast)--- TIP 9: In versions below 8.0, the planner will ignore your desire to choose an index scan if your joining column's datatypes do not match
Re: [HACKERS] somebody could explain this?
What's happening here is that the multiplication, being floating point, has some accumulated error such that when you multiply it by 100 and convert it to an int, it hits the cutoff. Trivia... I heard a story many years ago that landed a programmer in prison... He worked on the program that calculated interest that was to be deposited into an account. Instead of rounding or truncating the amount beyond what the bank wanted to use, he saved the small fractional dollars (really micro-pennies) into an account. Soon he had several hundred thousand in the account - there is a lot of multiplication... He got caught. ---(end of broadcast)--- TIP 6: explain analyze is your friend
Re: [HACKERS] somebody could explain this?
Otto Hirr [EMAIL PROTECTED] writes: Trivia... I heard a story many years ago that landed a programmer in prison... He worked on the program that calculated interest that was to be deposited into an account. Instead of rounding or truncating the amount beyond what the bank wanted to use, he saved the small fractional dollars (really micro-pennies) into an account. Soon he had several hundred thousand in the account - there is a lot of multiplication... He got caught. Uh yeah, that story would be the plot to Superman II (and Office Space too). -- greg ---(end of broadcast)--- TIP 5: don't forget to increase your free space map settings