Pro*C Rounding Solution ***

From: LMayhew <lmayhew_at_aol.com>
Date: 6 Dec 1994 00:40:26 -0500
Message-ID: <3c0tga$cp1_at_newsbf01.news.aol.com>


:culberso_at_tybrin.com (Mike Culberson) writes
 

:I am working on a SUN 630MP with Oracle 7.1.4.1.0, Pro*C 2.0.4.0.0, and
:SunOS 4.1.3_U1. The problem I am having is when I fetch a NUMBER column
 from
:a table the value referenced in the host variable is not the exact
:number value in table. I am working with an accounting system and numbers
:need to be exact. Example of code follows.

:oracle_table
:------------
:
:val NUMBER(11,2) with a value of 1.55
:
:code
:----
:
:#include <stdio.h>
:
:EXEC SQL BEGIN DECLARE SECTION;
: double value;
: char oracleid = '/';
:EXEC SQL END DECLARE SECTION;
:
:EXEC SQL INCLUDE sqlca;
:
:main ()
:{
: EXEC SQL CONNECT oracleid;
:
: EXEC SQL SELECT val
: INTO :value
: FROM oracle_table;
:
: printf ("value = %15.30g\n",value);
:}
:
:If val is 1.55 the value printed out would be
 1.55000000000000004440892098501
:
:Since I am dealing with multipling rates and calculating totals this
 causes
:my totals to be off. So far the only way to ensure correct calculations
 are
:to make all numbers integer within the Pro*C program. Are there any math
:libraries out there that would solve the problem.

First you might try using ROUND(val,2) on the select. So you'd have:

	EXEC SQL SELECT ROUND(val,2)
		 INTO   :value
		 FROM   oracle_table;

If that doesn't work, you'll need to round the double variable. Enclosed is a function that I wrote and use all the time, it uses some C functions that I believe are common to most compilers ( this is from a MSC Compiler).

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

double rnd_dble( double dd, int i )

{

  double l;
  double w, x, y, z;

  /* Seperate integer and fractional part of double */   x = modf( dd, &y );

  /* Multiply fractional part, making an integer */   x = x * pow(10.0,i);

  /* Test for sign */

  l = 1.0;
  if ( x < 0.0 ) l = -1.0;

  /* Find integer largest integer less than or equal to fractional part */   z = floor(x);
  w = x - z;

  /* Check difference, so that we can round up or down */   if ( w > 0.49 ) z = z + 1.0;

  /* Shift fractional part and add to original integer for rounded value */
  y = y + ( z / pow(10.0,i) );

  /* Set sign */
  y = y * l;

  return( y );

}

Hope this helps...

Lee Received on Tue Dec 06 1994 - 06:40:26 CET

Original text of this message