while adding the value and returning the result, it returns the correct value but when we return array values it is showing result with decimal values as shown in the below:
<?php return [1.4 + 11.3]; ?>
Output: 12.700000000000001
<?php return (1.4 + 11.3); ?>
Output: 12.7
How to resolve these issues? Any help would be great.
Thank you in advance.
This is known problem when getting currency from database.
I assume you use column type decimal.
There are some solution available:
Use casts [ 'amount' => 'decimal:2', ]
You can use a getter (laravel mutators) inside your model, formatting the result you get from db round($value, 2)
Use brick/money library or laravel-money package (but this solution is not for everyone)
Another solution, which the one I use, is converting column to type integer. You need to use mutator : setter convert decimal into integer, value 11.3 into 1130.and getter to process into decimal, from 1130 back into 11.3.
Related
I have a function which returns a value of 1725.00 using the number_format(value,2). So, now when I convert it to float, it gives 1, same for int,intValue,floatValue. Even I tried multiplying with 100 to get the int value, but it gives an error of A non well formed numerical value. Does anyone know what is wrong here?
$balance = (float) currentBalance($user_id); // currentBalance gives a value of 1725, but (float) gives makes the value 1.
print_r($balance); die; //gives 1.
I'm using PHP 7.0+ and Laravel 5.8.
Your problem is that number_format returns a string with commas inserted for thousand separators, so the return value from your function is 1,725.00. When you try to cast this as a float PHP gets as far as the comma and says this is no longer a number and so returns 1.
If you need to have a formatted string returned by currentBalance, your best bet is to use
$balance = (float)str_replace(',', '', currentBalance($user_id));
Otherwise, replace the call to number_format with a call to round so that currentBalance returns a numeric value instead.
I have a number 00101 when I print out this number (or using it for my purpose) I got 65, I've tried intval() but it also returns 65. Can anyone explain to me why? And what is the easiest way to get 00101, or 101?
I would say you are using an invalid type of number, there is bits type (see the list of types in https://www.php.net/manual/en/langref.php)
if you run the following
$a = array(10101, 11100, 11010, 00101);
var_dump($a);
you will see that PHP convert your number to int 65
so maybe you want to use strings?
You will get 101 from string '00101' when passing to intval function. However an integer number does not have start with leading 0; PHP does not get it as decimal number.
I've read all over about arithmetic regarding floating point numbers, but I'm just trying to accurately store the darn things.
I have a mysql field with the type of DECIMAL (40,20).
I am saving a value in php of 46457.67469999996. After updating the record with this value, the end result is 46457.67470000000000000000. Not sure why it's being rounded at all just being saved to the database.
The value is not being converted to a string or anything beforehand. The field value that is passed into PDO is the value I expected to be saved and it is returned as a float... Perhaps it's because I'm saving a PHP float to a mysql decimal type where the rounding is occurring?
What am I missing here?
EDIT: Added example code that has the issue
// Query placeholder variables. Hard-coded for the example test
$query_vars = array(
":vendor_id" => 33154,
":year" => 2018,
":coop_committed_dollar" => 46457.67469999996,
":coop_committed_dollar_update" => 46457.67469999996
);
$statement = " INSERT INTO vendor_data_yearly
(vendor_id, year, coop_committed_dollar) VALUES
(:vendor_id, :year, :coop_committed_dollar)
ON DUPLICATE KEY UPDATE
coop_committed_dollar = :coop_committed_dollar_update;";
$query = $connection->conn->prepare($statement);
$query->execute($query_vars);
When I run this, the resulting value of coop_committed_dollar is 46457.67470000000000000000. This code is legit all I am doing.
Possible solution
// Note that I am casting the string using the BC Math library.
// I dunno how to just initialize the number (lame documentation), so I'm adding 0 to it.
$number = "46457.674699999967";
$number = bcadd("46457.674699999967", 0, 20);
$query_vars = array(
":vendor_id" => 33154,
":year" => 2018,
":coop_committed_dollar" => $number,
":coop_committed_dollar_update" => $number
);
$statement = " INSERT INTO vendor_data_yearly
(vendor_id, year, coop_committed_dollar) VALUES
(:vendor_id, :year, :coop_committed_dollar)
ON DUPLICATE KEY UPDATE
coop_committed_dollar = :coop_committed_dollar_update;";
$query = $conn->prepare($statement);
$query->execute($query_vars);
This results in the number as expected in the DB.
ONLY SOLUTION I FOUND TO WORK CORRECTLY
The data I am working with is passed in via ajax. I had to take a few steps to get this to work correctly.
Use ini_set('precision', 20);
Manually set the data in question to be a string BEFORE sending it via ajax so PHP would not round it, extended with extra floating point madness, padd it, etc.
I found that PHP would just not let me reliably work with large numbers coming from a variable set outside the script's scope (ajax). Once PHP got it's hands on the number, it would do what it had to do in order to make it make sense as a float.
If anyone has a better solution for this particular scenario I'm all ears and eyes :)
The problem is that PHP's precision is not allowing you to store the exact number you think you are storing.
When you set ":coop_committed_dollar" => 46457.67469999996
PHP is actually storing it as a different value, depending on the precision.
The solution is to store the value in PHP as a string instead of a float.
Since your question is: "what am I missing", I will try to provide an answer.
Basically it comes down to storing floats internally using binary representation. Since 46457.67469999996 cannot be exactly in binary (it ends up with an infinite number, similar to 33% (.3333...) in base-10), the closest rounding is used based on PHP's precision (set in php ini).
I was given a great explanation in this question that I asked a while back.
In your particular case, it also seems that the value that you are sending via AJAX is being stored as a float when parsed by PHP on the server-side. You want it to be stored as a string instead. If you're using json_decode, add this option: JSON_BIGINT_AS_STRING.
I have a small issue with BIG numbers where BC Maths function bcdiv is always returning zero on non-zero results.
For example :
echo bcdiv(40075036, 86164.098903691, 40);
Versus the traditional method :
echo (40075036/86164.098903691);
I am not sure why the discrepency. Do BC Math functions only work on strings, and if so, how can i convert int values into strings before hand (inline notation preferred such as (int)$myvar; ) --- if that is the problem.
The solution to this problem was as follows:
bcmath operations only work with strings. You can not pass any other type of data as the parameters as it will not do any calculations unless the values are (string).
The set of functions will not automatically convert or cast the data into string, and NO ERROR WILL BE RETURNED if passing other data types.
To pass the data that is stored in an integer, float, etc, the following code will work for dynamic conversion of the variable data as needed:
bcdiv((string)40075036, (string)86164.098903691, (string)40);
OR
$num1 = 12345;
$num2 = 45678;
$digits = 40;
bcdiv((string)$num1, (string)$num2, (string)$digits);
If the numbers are fixed and known BEFORE you pass (aka, they aren't coming from a database, and aren't pre-calculated), then you should use the function as follows :
bcdiv('40075036', '86164.098903691', '40');
Use the "bcscale" function - Set default scale parameter for all bc math functions.
Ex.:
bcscale(40);
echo bcdiv(40075036, 86164.098903691);
It worked for me. (php 7.1)
bcscale manual
I am aware that the function may be computed manually using factorials, the problem is that larger numbers will not calculate properly.
For example, if I input COMBIN(1500,5) in MS Excel it will return 62,860,358,437,800 as it should. But if I try to calculate it manually, even in Excel I will get a #NUM! error when I try to first find the factorial of 1500. The manual formula would be
1500!/5!(1500-5)!
I find it curious that Excel's COMBIN function calculates properly yet the manual way returns an error. In short, I am wondering if there is an equivalent of this function in PHP? I have already tried manually computing using gmp_fact and as with Excel, it returns error (NaN).
Thanks
Your calculation is failing because you're quickly overflowing the Integer data type, which is probably just 32-bits on your system. You could use the arbitrary precision math functions to get around that problem:
http://www.php.net/manual/en/ref.gmp.php
If gmp_fact(...) seems to be returning errors or bad results, you're probably passing it a bad value or assuming it's result is a basic numeric type. You'll want to use something like gmp_strval to convert the returned GMP resource into something readable when you're done performing calculations.
Example:
$a = gmp_fact(1500);
$b = gmp_fact(5);
$c = gmp_fact(1500-5);
$result = gmp_div($a,(gmp_mul($b,$c)));
echo gmp_strval($result);