Hm. That isn't really conducive to a SUM. If the SUM were all you were doing you could go
SELECT SUM(retail_price) AS total_price FROM products WHERE product_id='$Cases' OR product_id='$Motherboard' OR ... product_id='$Printer' OR product_id='$Scanner'
But then you'd have to go back and do all the individual items again. So no, it's not really a solution.
Instead of carrying around a lot of product_ids, if you had a unique identifier that you could assign to each quote, you could SELECT on that:
"SELECT SUM(retail_price) as total_price, retail_price, product_name, product_type FROM products where identifier='$whatever'"
where "product_type" is a 'Motherboard', or a 'CDRW', or an 'Operating System'. And then you'd have another table relating identifiers with product_ids.
This would also make life easier for you when it comes to adding another product 🙂
--
But that's just speculation. As for your situation:
I presume the individual $row[] elements contain floating point values - otherwise you'd have noticed something wrong in the individual items.
I'm still not clear on where the precision is going, unless it's something to do with the usual problem of representing real numbers exactly with only finite-precision arithmetic - 1/10 written as a binary number doesn't terminate: 0.0001100110011... so ends up getting rounded off. It may be these roundoff errors choking your total.
Instead of directly summing them up all at the end, I'd:
Before beginning the searches, put $total=0;
Instead of saying "$kb=$row['retail_price']" etc., replace it with $total+=100*$row['retail_price']. The extra factor of a hundred is to do all the operations in cents rather than dollars, and so ensure that we only ever have to deal with (exact) integer values. Then, after all the prices have been tallied, $total=(double)$total/100.; - with a typecast and a decimal point just to make doubly sure that PHP treats this operation as acting on floating-point numbers instead of integers.