C question
Posted in 1994
Topics: Connectivity: ESQL/C, 4GL & Embedded SQL
I have a puzzling question that I found 2 solutions for. One is inelegant, and the other is inefficient. First the problem: We need to calculate (in a C program) a total cost that is the sum of an invoice's detail lines' extended costs (qty * cst). The problem is that the detail line cost is a decimal(8,4), and the total cost is a decimal(10,2). Selecting sum(qty*cst) doesn't work because the detail lines need to be rounded to the penny on each line--something like selecting sum(ext_cst), except that the database is fairly normalized, and there is no extended cost. There are several programs involved, a 4gl program and 2 C programs. in the 4gl program, I simply define a decimal(8,2) as an extended line cost, and spin through the array summing that to get the total. To illustrate, consider the following: qty cst ext_cst 2 1.002 2.00 2 1.002 2.00 3 1.002 2.01 1 1.004 2.00 totals calculating by sum(ext_cst) 8.01 by sum (qty*cst) 8.02 The C programs (written by 2 others) are using doubles for the calculations of the costs before inserting them into the database. I explained how we needed to do the rounding, and, by way of example, wrote the following C program to show how to round at each line before adding to the total: #include <stdio.h> main() { int i; double d = 1.005; d = d + 0.005; /* add 1/2 cent so it rounds up when it truncates */ d = d * 100; i = (int) d; /*d = (double) i / 100; */ /*assign it back to the double rounded to the penny*/ printf("%d %f", i,d); return 0; } Actually, I originally did all the calculations in the same step as the assignment, but broke them out for clarity, and to narrow down the cause of the problem. No matter how I did it, I got the same results: 100 101.000000 This happened on 3 different machines: a 386 running MS DOS (Borland C++ v 3.0), a 486 running ATT/NCR Unix (Metaware C), and a Sun (SunOS and Sun C compiler). I found 2 solutions, but cared for neither. In one, I used a temporary string, sprintf(), and atoi(). I didn't like that one due to the overhead of sprintf(). In the other, I used 2 casts: i = (int) (float) d; I don't like this one because it's ugly, and because it shouldn't be needed. Thanks Brian Green (briang2621@aol.com)