Storing Age numbers expressed in decimals in MySQL - php

I have an age column that is currently varchar because i cannot figure out how to define it correctly.
the ages look like the following samples:
.03 / .3 / 1.33 / 20
i tried Decimal (4,2) but then i get something like 82.00! which i dont want.
I want under 1 to look like 0.2 or .2, or .25
I want age 82 to be just 82 and age 5 to be just 5.
do I have to do this in php after the case or is there a way to store the numbers without the extra 0's.
storing as varchar displays them correctly but does not allow for the proper search.

How you store a number and how you format it when printing it are not mutually exclusive things. Storing numbers as strings is about the worst thing you can do. Decimal(4,2) tells MySQL to store the number with up to 2 digits of precision for the integral part of your number and up to 2 digits of precision for the fractional part. This says nothing about how those digits can be printed, however. For example printf("%d", 1.01) gives you 1. Whereas printf("%.2f", 1.0123) gives you 1.01.
PHP has several functions that can assist with formatting such as sprintf, and number_format, not to mention Intl's NumberFormatter for i18n.
If all you want is to truncate the right-most 0s from the number when printing it you can try something like rtrim($number, '0.').
echo rtrim(1.00, '0.'); // 1
echo rtrim(1.10, '0.'); // 1.1
echo rtrim(1.11, '0.'); // 1.11
echo rtrim(10.01, '0.'); // 10.01
The only edge case you have to watch out for here is if the number is 0 you will end up with an empty string.

Storing age as a varchar will lead to unexpected behaviour for instance when you ORDER BY age in a query.
Use the right types that map to your data.
ON displaying numbers with/without decimal places, use your application language (PHP) to perform this function.

Related

PhpExcel how to turn off the default conversion of numbers to scientific notation

How to turn off the default conversion of numbers to scientific notation. When importing from an excel file, large numbers are automatically converted to scientific notation (3.5868405364945E+14 it should be:358684053649447).Is there any option to turn off conversion in PhpExcel?
Or reverse conversions from PHP? When I trying to use printf,
printf("%d", "3.5868405364945E+14"); // 358684053649450 wrong value
final number is inaccurate.
Sorry, you'll never get the full value again, it's been already rounded, because your number has 16 digits and 15 digits is the limit for numbers in Excel.
It happens at the entry point, when you enter a number that excedes 15 digits. EXcel will round it, modifying your entry forever.
It's similar as storing a decimal number like 1.2 as integer, you'll loose that 0.2, no matter what you do, it will be 1 forever.
The only solution for this is (too late in your case), storing the large number as text in the first place, just adding a single quote before the number: '358684053649447 instead of 358684053649447. Excel will interpret that as string, not as number, and you'll be able to save numbers higher than 15 digits.

php calculation with decimal(10,3) results in exponential sometimes

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.

PHP subtracting numbers strangely - returning long float values

I'm calculating fees (monetary) for something and PHP is behaving strangely when the amount is supposed to be 0.00. It's giving the final result as a floating number, not 0 which it should be.
In My database I have the following table
id | transaction_total | charge_fees | deposit_fee | amount_to_customer | fees_minus_total_difference
So when I go to check to make sure that the fees + amount paid - total = 0.00
(96.54 + .25 + 3.20 - 99.99) = 1.4210854715202E-14
Why is the result a floating number and not actually zero? The numbers are originally more decimal places, but I used number_format to put it into 2 places. Ex, charge fees may actually be 3.19987
number_format(3.19971,2,'.','') //equals 3.20
When I save this in my database it displays as 3.20. When I use it in the computation for the total/fee check, the result is not zero, albeit close.
Computers store numbers in binary, so when you try to represent a decimal number you may lose precision. That is what is happening here.
Some languages have exact-precision types, but PHP, unfortunately, does not. It does provide you with both BC Math and GMP, though. Using those here seems overkill, though. Using BC, you could do this though:
bcsub(bcadd(bcadd('96.54','0.25',2),'3.20',2),'99.99',2) = 0
Notice that you have to specify the number of decimal points (2) here also.
Generally, using floats and double for finances is frowned upon, but with PHP it does seem like the simpler option.I suggest you just round your number using round() to the number of decimal places of your input.
round(96.54 + .25 + 3.20 - 99.99,2) = 0
I would recommend not using number_format() other than for displaying strings. Use round() instead.
Your issue is with floating points. PHP has more accurate math functions you can look at like bcadd, bcmul, bcdiv, etc...
http://php.net/manual/en/book.bc.php

data field type for decimal does not work as required

I have field where i store my grand total to a mysql filed as total and its type set as decimal(10,2)
When my php form adds up and updates the query for 112381348.40 (i.e 112 million)
but when i fetch or view it on phpMyadmin, the value shows as 99999999.99
from my data type set, it has to be 10 digits and 2 decimals where as it is maximum updating as 8 and 2.
Am i understanding wrong or what am i doing wrong.
I know i can increase it to decimal(13,2) and then see it.
But i would like to know the reason, why 10,2 is not happening?
The specification for decimal(m, n) takes two arguments. The first is the "precision" and the second is the "scale". More colloquially, the first is the number of digits in the number. The second is the number of digits to the right of the decimal point.
So, your specification of decimal(10, 2) can store numbers like: 12,345,678.90 -- i.e., up to 99,999,999.99. And that is the maximum number.
If you want to store numbers larger than that, then use a larger precision for the number. For your number, you need at least decimal(11, 2), although I would suggest a larger precision so you don't encounter this problem in the future.
In setting a float or decimal field, the first int value is the total character count. The second is how many decimal places. So:
//decimal(10,2)
12345678.90
//decimal(13,2)
12345678901.23
//decimal(7,3)
1234.567
See?
You have 11 digits. The first number is the total digits. Try:
DECIMAL(11, 2)

MySQL & PHP decimal precision wrong

24151.40 - 31891.10 = -7739.699999999997
I grab these two numbers from a MySQL table with the type as decimal(14,2)
24151.40
31891.10
It is saved exactly as stated above and it echos exactly like that in PHP. But the minute I subtract the second value from the first value, I get a number -7739.699999999997 instead of -7,739.7. Why the extra precision? And where is it coming from?
From an article I wrote for Authorize.Net:
One plus one equals two, right? How about .2 plus 1.4 times 10? That equals 16, right? Not if you're doing the math with PHP (or most other programming languages):
echo floor((0.2 + 1.4) * 10); // Should be 16. But it's 15!
This is due to how floating point numbers are handled internally. They are represented with a fixed number of decimal places and can result in numbers that do not add up quite like you expect. Internally our .2 plus 1.4 times 10 example computes to roughly 15.9999999998 or so. This kind of math is fine when working with numbers that do not have to be precise like percentages. But when working with money precision matters as a penny or a dollar missing here or there adds up quickly and no one likes being on the short end of any missing money.
The BC Math Solution
Fortunately PHP offers the BC Math extension which is "for arbitrary precision mathematics PHP offers the Binary Calculator which supports numbers of any size and precision, represented as strings." In other words, you can do precise math with monetary values using this extension. The BC Math extension contains functions that allow you to perform the most common operations with precision including addition, subtraction, multiplication, and division.
A Better Example
Here's the same example as above but using the bcadd() function to do the math for us. It takes three parameters. The first two are the values we wish to add and the third is the number of decimal places we wish to be precise to. Since we're working with money we'll set the precision to be two decimal palces.
echo floor(bcadd('0.2', '1.4', 2) * 10); // It's 16 like we would expect it to be.
PHP doesn't have a decimal type like MySQL does, it uses floats; and floats are notorious for being inaccurate.
To cure this, look into number_format, e.g.:
echo number_format(24151.40 - 31891.10, 2, '.', '');
For more accurate number manipulation, you could also look at the math extensions of PHP:
http://www.php.net/manual/en/refs.math.php
This has to do with general float / double precision rates, which scientifically relates to 1.FRACTAL * 2^exponential power. Being that there's a prefix of 1, there's technically no such thing as zero, and the closest value you can obtain to 0 is 1.0 * 2 ^ -127 which is .000000[127 0s]00001
By rounding off your answer to a certain precision, the round factor will give you a more precise answer
http://dev.mysql.com/doc/refman/5.0/en/mathematical-functions.html#function_round

Categories