I have one PHP script inserting rows in a MySQL database. Each row has a field 'created_at' which is filled with the value of the PHP function microtime(true), and inserted as a double. (microtime because I need something more precise than to the second)
I have another PHP script that selects rows based on that created_at field.
When I go ahead and select like this:
SELECT * FROM `ms_voltage` WHERE created_at > 1302775523.51878
I receive a resultset with, as the first row, the row with exactly that value for created_at.
This occurs from within my PHP script and from within PhpMyAdmin when manually doing the query. But not always, not for every value. Just once and a while really.
How is this possible? I didn't ask for greater than/equals, I want strictly greater than.
Am I overlooking something type-related perhaps?
Yeah, floating point arithmetic can do that sometimes. To understand why, it's helpful to realize that just as not all numbers can be accurately represented in base 10, not all numbers can be accurately represented in base 2 either.
For example, "1/3" may be written in base 10 as 0.33333 or 0.33334. Neither is really "correct"; they're just the best we can do. A "DOUBLE" in base 10 might be 0.3333333333 or 0.3333333334, which is double the digits, yet still not "correct".
The best options are to either use a DECIMAL value, or use an INT value (and multiply your actual values by, say, 10000 or 100000 in order to get the decimal digits you care about into that int).
The DOUBLE type represent only approximate numeric data values. Try to use the DECIMAL type.
Is your column floating point? Calling microtime with true gives you a float, and that looks like a float, which will have digits after the .51878 that you don't see, so those digits make the stored value greater than the value you have in your query.
Unless you really need the float I'd convert the string result to an int, or even two columns for seconds and useconds. Then you can use > or < on known values without worrying about the imprecision of the floating point value.
Related
I would like to know the proper way to insert decimals to a MySQL database
When I use the type decimal and if I enter 0.20 to the database its saving the value as 0
And when I use the type float and if I enter 0.20 to the database its saving the value as 0.2
I want to display the same value that enter and also, I want to use this value for filters. So, I don’t want to use the varchar type to inset these values.
Can someone tell me what is the best way to do this? I wouldn't mind using PHP to display the missing end zero.
Appreciate your time.
10,0 means 10 characters 0 of which are decimal. 10,2 would mean 8 numbers to the left, 2 to the right of the decimal.
Float should only be used when you are dealing with extremely large or small numbers; like the number of atoms in the galaxy where precision does not matter but scale does.
Lastly don't mix the concepts of "Display"(format) and value. Display is a formatting matter. The value 0005.50000 is the same as 5.5. Their display is just a matter of formating.
Here is my table:
Let us suppose I want my account balance to be:
0.4729472846758294728572
So I tried to set it to it but it keeps cutting it off and rounding up.
How can I stop this behavior?
FLOAT values are approximate:
The FLOAT and DOUBLE types represent approximate numeric data values.
If you need arbitrary precision you can use a DECIMAL column instead, e.g. DECIMAL(25, 20). In this case you'll get 5 digits before the decimal and 20 after.
MySQL permits a nonstandard syntax: FLOAT(M,D) or REAL(M,D) or 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. MySQL performs rounding when storing values, so if you insert 999.00009 into a FLOAT(7,4) column, the approximate result is 999.0001.
see here:https://dev.mysql.com/doc/refman/5.7/en/floating-point-types.html,
http://code.rohitink.com/2013/06/12/mysql-integer-float-decimal-data-types-differences/
I have single record on a table. So on MySQL when
select myamount from table 1 -- returns amount 420.67
But when i do MySQL as
select sum(myamount) from table 1 -- returns amount 420.8699951171875
should n't it return same amount 420.67 since I have only one record? and how to get amount 420.67 if SUM used.
Any help is appreciated and yes myamount datatype is float.
Float variables are stored in "scientific notation" (the 2,4E+04 format, which is the same as 2,4*10^4). But to make it even worse, it is also stored in binary. When calculating things with numbers stored as float, you may get a bit strange results because of this.
This video by Computerphile describes the problem very nicely.
In my php script I do a calculation of entries from a MySQL db. The concerning fields in the db are defined as decimal(10,3). It's an accounting plattform where I have to check if in every entry debit = credit.
I do this with the following operation:
$sumupNet = 0;
$sumup = 0;
foreach($val['Record'] as $subkey => $subval)
{
$sumupNet = $sumupNet + $subval['lc_amount_net'];
$sumup = $sumup + $subval['lc_amount_debit'] - $subval['lc_amount_credit'];
}
Now we say every entry is correkt, then $sumupNet and $sumup results in 0. In most cases, this works. But in some cases the result is something like this: -1.4432899320127E-15 or this -8.8817841970013E-15. If I calculate this values manually, the result is 0. I guess (not sure) that the above results are numbers near 0 and are outputted in the form of exponential.
So I think I have to convert something or my calculation is wrong. But what? I tried floatval() at some points but didn't work. If anybody has a hint, I thank you very much.
You're getting this because you are doing math with floating-point values. Read some theory about it.
You really don't want to calculate money like that as you might get weird rounding problems that you can't really do anything to fix.
For PHP, there are plenty of libraries that help you evade the problem, such as BC Math, or GMP.
Other solution would be to calculate all of the values using the smallest monetary value that the currency has (like cents) so you are always using integers.
These are rounding problems. These are perfectly normal when we are talking about floats. To give you an everyday example,
1/3 = 0.3333333333333333...333333333...3333...
Reason: 10 is relative prime with 3. You might wonder where is 10 coming from. We are using 10-base for numbers, that is, whenever we speak about a number, its digits represent 10-base exponential values. The computer works with binary numbers, that is, 2-base numbers. This means that division with such numbers often result in endless sequences of digits. For instance, 1/3 as a binary number looks like this:
0.010101010101010101010101010101010101010101010101010101...
Decimal types are representing decimal numbers, that is, 10-base numbers. You use three digits for the part after the . Let's supose your number ends like this:
.xyz
this means:
xyz / 1000
However, 1000 can be divided with the following prime numbers:
2 and 5.
Since 5 is relative prime with 2, whenever you are representing the result of a division by 5 as a binary number, there is a potential that the result will be an endless cycle of digits. 1/5 as a binary number looks like this:
0.0011001100110011001100110011001100110011001100110011...
Since a computer cannot store endless digits, it has to round the number, that is, find a number close to its value which can be represented in an easier manner. If the number a is rounded to b and the two numbers are not equal, then a certain amount of precision is lost and this is the reason of the bug you have mentioned.
You can solve the problem as follows: when you select the values from the database, multiply them by 1000 (thus, converting them into integers) and then check the operations. At the end, divide by 1000.
I have a table with a current structure as follows:
Currently this is populated as follows:
The data stored for product value is a decimal value
and the end digits are cut off once it is inserted into the database.
I have tried changing the table structure as follows:
However this only leads to the following:
As you can see all values have a .00 appended if none exists, however I want to
store all these values with no decimal places. Except the product value.
How can I do this?
The trouble is you are converting a decimal (float / double) to an integer, so the value is simply truncated (decimal values are chopped off).
If you really don't want to use floats (decimal values) in the database you can use this hack work around will work:
Multiply the number by 100 before inserting it, and then be sure to divide it by 100 when you use the data. This will allow you to maintain 2 decimal points while using integer storage.
Thus, 2.4 would be stored as 240, 53 would be 5300, 20.74 becomes 2074 etc...
I want to note that this is not an ideal solution, but rather a hack.
I highly recommend what the other users suggested in the comments: storing the decimal value (as you have) and formatting it when presenting it.
--- In addition ---
Your real problem appears to be with the way the database is setup.
Each of those values should have their own field since they will be repeated for each product.