I spotted some rounding bug in MySQL. Here is my query:
SELECT /*debugz*/ ROUND((SUM(grade)/2),0) AS grade, SUM(grade) FROM entry.computed_grade a WHERE a.stud_id='7901159' AND a.sy='2014' AND a.term=01 AND a.terms=01 AND a.catalog_no='Christian Life Formation';
and the result is this:
grade sum(grade)
------ ------------
92 185
The grade result should be 93, not 92 because 185/2 = 92.5
Try this
SELECT CEIL((SUM(grade)/2),0) AS grade, SUM(grade) FROM entry.computed_grade a WHERE ((a.stud_id='7901159') AND (a.sy='2014') AND (a.term=01) AND (a.terms=01) AND (a.catalog_no='Christian Life Formation'));
Try to use ceil instead of round.
e.g ceil(1.45) = 2
You should check rounding behavior artickle for mysql. I believe here is the reason of your problem:
For approximate-value numbers, the result depends on the C library. On
many systems, this means that ROUND() uses the “round to nearest even”
rule: A value with any fractional part is rounded to the nearest even
integer.
By the way it's IEEE standard for float point rounding, so you might want stay with it
Do not "patch" this problem by tweaking the query. Actually fix your database. If you are not storing the "grade" column as the DECIMAL data type, and are instead using FLOAT or DOUBLE, your design is inherently broken.
Because floating-point values are approximate and not stored as exact values, attempts to treat them as exact in comparisons may lead to problems.
http://dev.mysql.com/doc/refman/5.6/en/floating-point-types.html
This is not a bug in MySQL. It is an inherent limitation in industry-standard floating point number storage. Use DECIMAL columns to store meaningful, precise numbers, and the other two types only when low storage space or a wide range of allowable values are more important than precision.
I am creating for fun, but I still want to approach it seriously, a site which hosts various tests. With these tests I hope to collect statistical data.
Some of the data will include the percentage of the completeness of the tests as they are timed. I can easily compute the percentage of the tests but I would like true data to be returned as I store the various different values concerning the tests on completion.
Most of the values are, in PHP floats, so my question is, if I want true statistical data should I store them in MYSQL as FLOAT, DOUBLE or DECIMAL.
I would like to utilize MYSQL'S functions such as AVG() and LOG10() as well as TRUNCATE(). For MYSQL to return true data based off of my values that I insert, what should I use as the database column choice.
I ask because some numbers may or may not be floats such as, 10, 10.89, 99.09, or simply 0.
But I would like true and valid statistical data to be returned.
Can I rely on floating point math for this?
EDIT
I know this is a generic question, and I apologise extensively, but for non mathematicians like myself, also I am not a MYSQL expert, I would like an opinion of an expert in this field.
I have done my research but I still feel I have a clouded judgement on the matter. Again I apologise if my question is off topic or not suitable for this site.
This link does a good job of explaining what you are looking for. Here is what is says:
All these three Types, can be specified by the following Parameters (size, d). Where size is the total size of the String, and d represents precision. E.g To store a Number like 1234.567, you will set the Datatype to DOUBLE(7, 3) where 7 is the total number of digits and 3 is the number of digits to follow the decimal point.
FLOAT and DOUBLE, both represent floating point numbers. A FLOAT is for single-precision, while a DOUBLE is for double-precision numbers. A precision from 0 to 23 results in a 4-byte single-precision FLOAT column. A precision from 24 to 53 results in an 8-byte double-precision DOUBLE column. FLOAT is accurate to approximately 7 decimal places, and DOUBLE upto 14.
Decimal’s declaration and functioning is similar to Double. But there is one big difference between floating point values and decimal (numeric) values. We use DECIMAL data type to store exact numeric values, where we do not want precision but exact and accurate values. A Decimal type can store a Maximum of 65 Digits, with 30 digits after decimal point.
So, for the most accurate and precise value, Decimal would be the best option.
Unless you are storing decimal data (i.e. currency), you should use a standard floating point type (FLOAT or DOUBLE). DECIMAL is a fixed point type, so can overflow when computing things like SUM, and will be ridiculously inaccurate for LOG10.
There is nothing "less precise" about binary floating point types, in fact, they will be much more accurate (and faster) for your needs. Go with DOUBLE.
Decimal : Fixed-Point Types (Exact Value). Use it when you care about exact precision like money.
Example: salary DECIMAL(8,2), 8 is the total number of digits, 2 is the number of decimal places. salary will be in the range of -999999.99 to 999999.99
Float, Double : Floating-Point Types (Approximate Value). Float uses 4 bytes to represent value, Double uses 8 bytes to represent value.
Example: percentage FLOAT(5,2), same as the type decimal, 5 is total digits and 2 is the decimal places. percentage will store values between -999.99 to 999.99.
Note that they are approximate value, in this case:
Value like 1 / 3.0 = 0.3333333... will be stored as 0.33 (2 decimal place)
Value like 33.009 will be stored as 33.01 (rounding to 2 decimal place)
Put it simply, Float and double are not as precise as decimal. decimal is recommended for money related number input.(currency and salary).
Another point need to point out is: Do NOT compare float number using "=","<>", because float numbers are not precise.
Linger: The website you mention and quote has IMO some imprecise info that made me confused. In the docs I read that when you declare a float or a double, the decimal point is in fact NOT included in the number. So it is not the number of chars in a string but all digits used.
Compare the docs:
"DOUBLE PRECISION(M,D).. Here, “(M,D)” means than values can be stored with up to M digits in total, of which D digits may be after the decimal point. For example, a column defined as FLOAT(7,4) will look like -999.9999 when displayed"
http://dev.mysql.com/doc/refman/5.1/en/floating-point-types.html
Also the nomenclature in misleading - acc to docs: M is 'precision' and D is 'scale', whereas the website takes 'scale' for 'precision'.
Thought it would be useful in case sb like me was trying to get a picture.
Correct me if I'm wrong, hope I haven't read some outdated docs:)
Float and Double are Floating point data types, which means that the numbers they store can be precise up to a certain number of digits only.
For example for a table with a column of float type if you store 7.6543219 it will be stored as 7.65432.
Similarly the Double data type approximates values but it has more precision than Float.
When creating a table with a column of Decimal data type, you specify the total number of digits and number of digits after decimal to store, and if the number you store is within the range you specified it will be stored exactly.
When you want to store exact values, Decimal is the way to go, it is what is known as a fixed data type.
Simply use FLOAT. And do not tack on '(m,n)'. Do display numbers to a suitable precision with formatting options. Do not expect to get correct answers with "="; for example, float_col = 0.12 will always return FALSE.
For display purposes, use formatting to round the results as needed.
Percentages, averages, etc are all rounded (at least in some cases). That any choice you make will sometimes have issues.
Use DECIMAL(m,n) for currency; use ...INT for whole numbers; use DOUBLE for scientific stuff that needs more than 7 digits of precision; use FLOAT` for everything else.
Transcendentals (such as the LOG10 that you mentioned) will do their work in DOUBLE; they will essentially never be exact. It is OK to feed it a FLOAT arg and store the result in FLOAT.
This Answer applies not just to MySQL, but to essentially any database or programming language. (The details may vary.)
PS: (m,n) has been removed from FLOAT and DOUBLE. It only added extra rounding and other things that were essentially no benefit.
I am trying to save a float in my MySQL database as a decimal(20,10). But I don't think this is a good way, because when I try to save 2.14 it will save 2.1400000000.
At least this one is better than float(20,10) because that one was rounding it wrong.
But which type should I use to store it as 2.14? I can't just say 20,2 because sometimes I have for example 34.2222291 as value.
SOLUTION:
double(20,10) fixed it.
The difference between 2.14 and 2.1400000000 is just an issue of output formatting (in whatever language you use for that - but even possible with MySQL if you will).
So if you want exact decimal values, DECIMAL(20,10) is the way to go. DOUBLE (double precision floating point) just has less rounding problems than FLOAT (single precision floating point), it does not eliminate them because it is still a floating point type.
The round function sometime doesn't work very well. I have in my db a row like this:
field_1= 375
field_2= 0.65
field_3= 0.1
field_4= 11
So we know that: field_1*field_2*field_3*field_4 = 268.125 so if I round it to 2 decimals -> 268.13.
But in mysql I got 268.12 -> Select round(field_1*field_2*field_3*field_4) from my table -> 268.12
This situation just happens with these values, I tried with other numbers and no problem the round works.
Any workaround about it. I tried in mysql 4.1.22, and 5.1.44 and I get the same issue. I read in other forum http://bugs.mysql.com/bug.php?id=6251 that it is not a bug, they said that it depends on the C library implementation.
What data type are you using for those columns?
If you want exact precision then you should use NUMERIC or DECIMAL, not FLOAT, REAL, or DOUBLE.
From the manual:
The DECIMAL and NUMERIC types store exact numeric data values.
These types are used when it is important to preserve exact precision,
for example with monetary data.
If applicable you can use FLOOR()
If not applicable you will be better off handling this on the application side. I.e. do the entire calculation application side and then round, or just round application side.
SELECT (field_1*field_2*field_3*field_4) AS myCalculation FROM my table
Look at this query please
SELECT max( val_amd ) FROM `best_deposits`
I have the max value in the table equal to 14.6(the fields has type float),
But it returns 14.3599996566772
why does it happen, and how can i get the exact value?
Thanks much
floats are evil!
NEVER use floats for storing amounts or prices. instead of that, use an int and store the amount in cents. thats the only way to get around those problems forever.
why this happens: because floats can't be saved exactly in many cases (such as 0.6 in your case)
PS: we had those questions a hundret times for different languages till now:
Use Float or Decimal for Accounting Application Dollar Amount?
PHP rounding problem (5.2.3)?
Rounding problem with double type
Javascript rounding v c# rounding
Python rounding problem
... and a lot more
EDIT: to your comment: as i said:
use an int and store the amount in
cents
(alternatively you could use an DECIMAL(10,2) (or how big/how much decimal places you need)... not sure about how this works)
Or you better use "decimal" with length 10,2 or something like that for storing prices.