Float or decimal for prices? - mysql

Which type (Float or decimal) is best used to store prices in a mysql database?

Floats are not exact and can introduce cumulative rounding errors. Decimal is the best format for financial information that must be exact.

Prices are decimal values, and calculations on them are expected to behave like decimal fractions when it comes to rounding, literals, etc.
That's exactly what decimal types do.
Floats are stored as binary fractions, and they do not behave like decimal fractions - their behaviour is frequently not what people used to decimal math expect. Read The Floating-Point Guide for detailed explanations.
For money values, never never use binary float types - especially when you have a perfectly good decimal type available!

For Financial calculations use Decimal
According to IEEE 754 Floats were always binary, only the new standard IEEE 754R defined decimal formats. Many of the fractional binary parts can never equal the exact decimal representation. Any binary number can be written as m/2^n (m, n positive integers), any decimal number as m/(2^n*5^n). As binarys lack the prime factor 5, all binary numbers can be exactly represented by decimals, but not vice versa.
0.3 = 3/(2^1 * 5^1) = 0.3
0.3 = [0.25/0.5] [0.25/0.375] [0.25/3.125] [0.2825/3.125]
1/4 1/8 1/16 1/32
So for Financial calculations use Decimal not FLOAT

When we store a number in float we don't save the exact number,it is an approximation. The integer part gets the priority and fractional part is as close as the type size. So if you have calculations and need accurate result use Decimal.

Please Use BigDecimal , as it is the best for the prices , since pennies are rounded properly to dollar.
Joshua Bloch recommends BigDecimal.

Related

What is precision of MYSQL RAND() function? and how to generate huge random numbers?

What is precision of MYSQL RAND() function?
I can't find it on the official page: MYSQL RAND() function is told to return floating-point number, unfortunately it's precision is not stated in a clear way. It can be a single-precision floating-point data, or double-precision, or any other kind of data.
What I would like to know exactly is - what is the maximum integer range [0,N] in which I can generate random integer numbers with FLOOR(RAND()*N) such that there won't be any "skips" and any number from 0 to N can be generated?
Another thing which I would like to know:
How to generate numbers, which are bigger than N in MySQL?
As written in the MySQL docs the precision is system dependent. So there is not the one answer to your question.
https://dev.mysql.com/doc/internals/en/floating-point-types.html
Since MySQL uses the machine-dependent binary representation of float and double to store values in the database, we have to care about these. Today, most systems use the IEEE standard 754 for binary floating-point arithmetic. It describes a representation for single precision numbers as 1 bit for sign, 8 bits for biased exponent and 23 bits for fraction and for double precision numbers as 1-bit sign, 11-bit biased exponent and 52-bit fraction. However, we can not rely on the fact that every system uses this representation. Luckily, the ISO C standard requires the standard C library to have a header float.h that describes some details of the floating point representation on a machine. The comment above describes the value DBL_DIG. There is an equivalent value FLT_DIG for the C data type float.
At the end I have no clue why the precision of a random number is important in any case. I cannot see any use case

What is wrong with my IEEE 754 floating point representation?

I am being asked in a homework to represent the decimal 0.1 in IEEE 754 representation. Here are the steps I made:
However online converters, and this answer on stack exchange suggests otherwise. They put this solution:
s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm
0 01111011 10011001100110011001101
The difference is the number 1 at the right. Why isn't it 1100, why is it 1101?
As njuffa said in a comment, rounding is the explanation for the difference you see. Converters usually produce the nearest floating-point value to the decimal number you put in. The IEEE 754 standard recommends that the rounding mode be taken into account for conversions from one base to another (such as from decimal to binary), and the default rounding mode is “to nearest”.
The two closest single-precision floating-point values to 1/10 are 1.10011001100110011001100×2-4 and 1.10011001100110011001101×2-4 (below and above 1/10).
The digits that are cut off are “11001100…”, indicating that the real 1/10 is closer to the upper bound than to the lower bound(if the remaining digits had been “100000000…”, the real number would have been exactly in-between the two). For this reason, the upper value 1.10011001100110011001101×2-4 is chosen as the conversion of 1/10 to binary32 when converting in round-to-nearest mode.

Why does the binary fourteen bit floating point model used in textbooks use bias 16 where as the IEEE single precision uses bias 127?

In my computer architecture course we use a 14 bit binary model;(1 bit for sign,5 bits for exponent, and 8 bits for our mantissa). When inputting the Exponent my instructor has us add 16 to offset it.(bias 16) Why are we using 16 bias? Is it because 5 bits can only represent up to 31 numbers? If so please elaborate and compare to IEEE single precision that uses a 127 bias when using the exponent. Lastly if someone can give me a clear definition of bias used in this context and in binary I would greatly appreciate it. Please comment if anything I said was unclear.
The IEEE 754 binary float formats follow a simple pattern for the exponent bias. When the exponent has p bits the bias is . With this the exponent has an equal number of positive and negative exponents.
For single precision floats p is 8 and therefore the bias is 127. For your format p is 5 and the bias is 15. Maybe your instructor changed the bias to 16 because the format don't support denorm, infinity and NaN.
There are several ways of representing a range of numbers including both positive and negative. Adding a bias is particularly flexible. The range [-n, m) can be represented by adding n to each number, mapping it to the range [0, m+n).
That system is used for the exponent in all the floating point systems I have used. It simplifies some comparisons, because larger unsigned binary value of the non-sign bits represents larger absolute magnitude of the float, except for special values such as NaNs.
For float exponents, the bias is around half the exponent range, so that approximately half the values are on each side of zero. Exact balance is impossible because there are an even number of bit patterns, and one is used for zero.
As discussed in another answer, the IEEE 754 standard would use a bias of 15 for a 5 bit exponent.
There are several possible reasons for choosing 16:
There is some actual technical reason, such as the suggested one of not treating 31 as special.
Bias 16 makes the representation of 1.0 particularly simple, with a single non-zero bit.
Being subtly different from IEEE 754 helps convince students that floating point does not imply IEEE 754. There are other floating point formats.
Being subtly different from IEEE 754 may discourage use of existing tools to get the results for exercises without understanding how the representation works.
It is an arbitrary choice of one of the reasonable values for the exponent bias, without reference to IEEE 754.

Storing statistical data, do I need DECIMAL, FLOAT or DOUBLE?

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.

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.