Mysql: money and floats - mysql

What float do I need to store such sums like these: $1,200,000, $1,000, and $14.56 ? ($ dosn't count; it will be removed)

Don't. Store as an int and multiply/divide by 100. e.g. Store 14.56 as 1456, but /100 when displaying. Floating point for storing currency is just asking for rounding problems.

Try DECIMAL. See http://dev.mysql.com/doc/refman/5.1/en/numeric-types.html

Related

Having a rough time decided on FLOAT, DOUBLE, or DECIMAL

Currently using MySQL version 5.1.6
This is my first real world build and so far I have actually been enjoying it; however, I now am stuck on a decision regarding a field datatype and hoping someone could sort it out for me.
I essentially have 10 fields that are all different test results. The numbers range from -100 to 100 and can have a decimal with one spot after the actual point.
For example, -5.1, 0, 1, 16.3, 99.2, and 100 are all possible data. From what I have read, one should use DECIMAL for those things that we usually measure and are exact (which these are), whereas FLOAT and DOUBLE are approximations, which I do not really want (though I am sure at this level, the approximation is very small if existent at all).
If I use DECIMAL, do I have to include a space for the '-' at the beginning if used? I.E, would I use DECIMAL(4,1) or DECIMAL(5,1) or am I way off here? I might be overthinking this a bit.
DECIMAL(4,1) will be enough, the sign digit does not need to be included.
More info: http://dev.mysql.com/doc/refman/5.1/en/precision-math-decimal-changes.html
For example, a DECIMAL(3,0) column supports a range of -999 to 999
Decimal will be indeed the best option for your needs. Float and Double can give you ugly numbers (e.g. 0.2 cannot be represented as float, you'd get 0.19999999)
The negative symbol does NOT count as a digit in your calculation, so DECIMAL(4,1) should be fine.
Edit: That also seems like the right field to use for your purposes. Try it out!

Storing decimal number with MySQL

What's the best type to store values such:
48.89384 and -2.34910
Actually I'm using float.
Use decimal for exact values.
Notes:
ABS (Latitude) <= 90
ABS (Longitude) <= 180
So you can us 2 different types
Latitude = decimal (x+2, x)
Longitude = decimal (y+3, y)
x and y will be the desired precision. Given a metre is 1/40,000,000 of the earth's circumferemce, something like 6-8 will be enough depending on whether you're going for street or full stop accuracy in location.
If you want exact representation, and you know the scale that applies, then you can use the decimal data type.
If you work with money use DECIMAL type. It has no floating-points inaccuracy.
#MiniNamin
if you are using sql then it will also work by putting the DataType Numeric(18,4)
The benefit of floating point is that it can scale from very small to very large numbers. The cost of this, however, is that you can encounter rounding errors.
In the case that you know exactly what level of accuracy you need and will work within, the numeric / decimal types made available to you are often more appropriate. While working within the level of accuracy you specifify on creation, they will not encounter any rounding errors.
That depends on what you're using the numbers for. If these numbers are latitude and longitude, and if you don't need exact representations, then FLOAT will work. Use DOUBLE PRECISION for more accuracy.
But for exact representations, use DECIMAL or NUMERIC. Or INT or one of its different sizes, if you'll never have fractions.

Rounded numbers returned as '0.999999999992345' sometimes

I have a report that should return something along the lines of
SELECT brand, ROUND(SUM(count * price) / SUM(count), 2)
WHERE ... GROUP BY brand, ...;
The problem is, I sometimes get 9990.32999999999992345 in my perl code instead of 9990.33 which direct SQL request returns.
The number starts looking that way right after fetchrow_hashref, if it ever does. The same number can come in 'good' or 'bad' form in different queries, but always the same way in any specific query.
How can I track this down?
Read all about floating point accuracy problems here: http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
As mellamokb said, you have to round your floating-point numbers. More importantly, count and price probably means that you are calculating the price of something. As this page explains for the FLOAT and DOUBLE datatype, calculations are approximate while for DECIMAL they are exact. For your particular example, the chance is low that will give problems but not if you do a lot of calculations with your price. The usual rule is to always use exact datatypes for calculating prices.
Always round floating point numbers when displaying them on the screen. And do it as the final step as it is displayed. Any intermediate operation has the potential to cause problems like this.
I can think of a couple of causes of this, but first:
Does it make any difference to put a CONCAT( '', ... ) around your ROUND? What version of perl are you using? What does perl -V:nvtype report?
33/100 is a periodic number in binary just like 1/3 is a periodic number in decimal.
$ perl -e'printf "%.20f\n", 0.33'
0.33000000000000001554
Therefore, it would take infinite storage to store it as a floating point number. To avoid the problem, you'll need to store the number as a string, either early (in the query before it's a float) or late (by rounding).
It's an issue inherent with floating point numbers. It's a design feature, not a flaw.
Make sure the value returned from the database is not a floating point value, but a string or decimal. (If the data types of `price` and `count` are both DECIMAL, then the resulting expression should be DECIMAL.
If either of those is a floating point, then you can convert to DECIMAL...
SELECT brand, CONVERT( SUM(count * price) / SUM(count), DECIMAL(18,2) )
WHERE ... GROUP BY brand, ...;
Or convert to a string
SELECT brand, CONVERT(CONVERT( SUM(count * price) / SUM(count), DECIMAL(18,2)),CHAR)
WHERE ... GROUP BY brand, ...;
You can let the conversion to DECIMAL do the rounding for you. If you return a DECIMAL or VARHCAR to Perl, that should avoid floating point issues.
More generally, to handle representation (rounding) of floating point in Perl, you can format using the sprintf function, e.g.
my $rounded_val = sprintf(%.2f, $float_val);

mysql returns not exact value in max function when dealing with floats?

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.

Storing a floating point number as an INT?

what would be the best data type to store a floating point number in mySQL?
Can I somehow store it as an INT?
I am thinking that VARCHAR is my best option, but if you guys know of anything better I would appreciate the input.
Thanx in advance!
Depends on what type of floating point number you are storing, all details regarding MySQL numeric types can be found here:
http://dev.mysql.com/doc/refman/5.5/en/numeric-types.html
DECIMAL: For currency, you should use Decimal because its precise and you wont get weird decimal rounding in arithmetic.
INT: Yes you can store floats as ints to gain performance. For example currency can be stored as $19.56 or 1956 as long as you always / 100 when displaying, accounting software does this often. Furthermore you can store latitude / longitude as integers, 322274063, -1109654800 = 32.2274063, -110.9654800 as long as you divide by 10,000,000 when outside the database.
FLOAT / DOUBLE: And then of course there is long and double. Use them when performance is not a priority or the number of decimal places varies.
SO RULE: If performance is an issue and you know the decimal places are always a fixed length, you can easily store an INT to store a FLOAT.
I would use a Mysql Float type.
Why do you want to store a floating-point as an int? MySQL has decimal and float types just like your programming language.
I'll assume you have a good reason. To store a float as an int, you can try a few things:
Multiply the number by 10^n, where n is the number of significant digits you want to keep, and then truncate the rest of the fractional part. When you get it back out of the DB, convert to float/decimal and divide by n. This requires an int big enough to store the multiplied value; in 32-bit architecture, a "native" int can store values up to 2 billion.
Split the number into its integer part and its fractional part. This requires two fields, but each field can have a value up to the maximum integer value, allowing you to easily have precision in the hundred-millionths.
If you have to encode a floating point number in a flat format I'd recommend having a look at http://en.wikipedia.org/wiki/IEEE_754-2008