Substracting float from array - php

I have an array that contains multiple values with numerical index. The data type for each value is string. It was supposed to be a float number though (38.50, 22.12, etc).
What I want to do now is subtract each values from the array with a number that I'd like to specify myself. And then, find the absolute number in case the subtraction gives a negative number as the result.
How can I do that?

You want to look into the array_map() function.

I don't know if this is what you meant:
$original_array = array('38.50', '22.12');
function sort( $n ){
$num = 12.0;
return (double)$n - $num;
}
$newarray = array_map("sort", $original_array );
Converting an integer or a string to a float can be a pain though.
Using any of these functions will convert them to a proper float first:
function float_format( $number, $decimal = 2, $decimal_sep = '.', $thousands_sep = '' ){
return number_format($number, $decimal, $decimal_sep, $thousands_sep);
}
function float_val( $number, $decimal, $float_locale = 'f' ){
//f - the argument is treated as a float, and presented as a floating-point number (locale aware).
//F - the argument is treated as a float, and presented as a floating-point number (non-locale aware). Available since PHP 4.3.10 and PHP 5.0.3.
return (double)sprintf("%.".$decimal.$float_locale, $number);
}
The first of which is better for currency. Hope this helps.

Related

Convert array of values into a single float value in PHP?

I have an array with these values (when the array is printed with print_r();
Array:
[0] => 66
[1] => 233
[2] => 204
[3] => 205
The values in hex are:
Array:
[0] => 0x42
[1] => 0xE9
[2] => 0xCC
[3] => 0xCD
What I'm looking to do is to turn this 4 byte array into a float value. If I use implode(); to turn the array into a value, it just combines the string into 66233204205 instead of 0x42E9CCCD which are not similar. Thus I can't use floatval(). PHP is new to me, and so is using string values instead of the actual bits, like I can in C.
What I'm thinking is to some how implode() it with the hex values, instead of those integer numbers, and then use floatval().
Any ideas guys?
EDIT:
Just so it's a little clearer, I should be obtaining 116.900 as the result
You have to do a simple math operation to concatenate hex values of the array one after the other. The algorithm would be like this:
Assign the first hex value of the array to a resultant variable, $concat in this case.
Use a for loop to loop through the array from 2nd element till nth element
In each iteration of the loop left shift 8 times the existing hex value of the resultant variable and place the new hex value in the least significant 8 bits of the resultant variable.
// Suppose $array is your original array
$concat = $array[0];
$count = count($array);
for($i = 1; $i < $count; $i++){
$concat = ($concat << 8) + $array[$i];
}
// display concatenated hex value: 42e9cccd
var_dump(dechex($concat));
// Now do your operation on the concatenated hex value
Here's a demo, https://eval.in/844793
Revised Answer with ....
Performing math with hex strings used to be a feature supported in PHP. Now with PHP 7, a hex string only represents a string of characters and no longer is recognized as containing a numeric value. If you attempt to do math with it, the result is zero. Consider the following code:
<?php
$arr = [66, 233, 204, 205];
$res = array_reduce( $arr, function($c,$i) {
$c.=dechex( $i );
return $c;
});
$temp = "0x" . $res; // 0x42e9cccd
var_dump($temp + 0);
See demo
This code attempts to provide the hex string a mathematical context by adding zero to the value contained in $temp. This code works until PHP 7 because the powers that be determined that hexstrings created more problems than they were worth; see this RFC and the Manual:"Hexadecimal strings are no longer considered numeric".
Concatenation, being a string operation, creates the example's hex string whose direct usage proves unwise in a math operation. A notice will be emitted (in PHP 7.1), complaining as follows:
Notice: A non well formed numeric value encountered
You may suppress displaying this notice, but the resulting sum will be zero in PHP 7. When the code functions correctly in PHP 5.6, the result of 1122618573 seems wrong, certainly far too large to cast as a float and obtain the value that the OP seeks.
... A Bona Fide Work-Around
<?php
$arr = [66, 233, 204, 205];
$res = array_reduce( $arr, function($c,$i) {
$c.=dechex( $i );
return $c;
});
$temp = "0x" . $res;
$int = filter_var( $temp, FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX );
if (false === $int) {
throw new Exception("Invalid integer!");
}
$arr = (unpack('f', pack('i', $int )));
$f = array_pop($arr);
printf("%.3f",$f);
See demo
PHP will recognize the numeric hex string that array_reduce() yields if you use filter_var() with the indicated parameters. In this fashion, you may obtain an integer evaluating as 1122618573. The key thing rather than the integer's value is its binary bit pattern. Borrowing from the official answer here, the code needs to pack $int into a binary string, which it subsequently will unpack as a float -- almost. That result will be returned as an array with just one element. After popping off and capturing that element's float value, printf() displays 116.900.
This appends the values of the array to eachother (in hexadecimal). PHP's dechex() function.
http://php.net/dechex
dechex — Decimal to hexadecimal
$b = [66,233,204,205];
$a = dechex($b[0]);
for($x = 1; $x < count($b); $x++) {
$a = $a . dechex($b[$x]);
}
echo $a; // $a = 42e9cccd
You didn't specify if your array represents an integer, if is the integer part of the floating point value, or is the entire number represented in IEEE 754 format.
Anyway, I would suggest you to take a look at the "pack" function.
$value = pack('i', your_value);
HERE you can find the documentation: basically you have to provide the type you want to obtain, along with your value(s), of course.
Also PHP is NOT a strongly typed language, so you don't have to distinguish integer from floats, in this case. You can treat integer like floats, and viceversa. But if you want to be 100% sure, just do something like this:
$value = floatval(pack('i', your_value));
This is, of course, machine dependent, but I don't know of any machine running PHP that doesn't use IEEE 754 floats.

Correct the float values

I read some data from a csv file. Each line in the file has a float value. these values can be either:
.123 : starting with a period, so I need to add a zero before.
1,23: having a delimter comma ',' instead of period so I need to change that.
1.2e3 having an exponential-format so I need to convert it to decimal format.
I can't use the function number_format because I can't set the number of decimal points (the float numbers don't have a fixed length of the decimal part and we want to take them as they are to not lose data).
Here is what I tried so far; I built two functions, the first one filters the floats, the second one corrects them when the filter returns false:
function validateFloat($float){
if(!filter_var($float,FILTER_VALIDATE_FLOAT,array('flags' => FILTER_FLAG_ALLOW_FRACTION))){
return false;
}
}
function correctFloat($float){
if (validateFloat($float)==false){
$number = number_format($float,null,'.');
str_replace($number,'',$line);
}
}
I don't know how to build the correctFloat function. Any suggestions ? Appreciate it.
Your function can check if there is a comma and get the correct deliminator then use floarval on any other case
function change_format($value){
if(is_string($value)){
//has to be a string if using ','
$value= str_replace(",",".",$value);
}
return floatval($value);
}
echo change_format(.123) ."<br>";
echo change_format("1,23") ."<br>";
echo change_format("1.2e3");
Outputs:
0.123
1.23
1200

How to make it decimal (1.25, 1.65 etc) (php)

I'm using MongoDB as a database.
And I've made some record just like "1.65" "1.25" "1.95" etc.
But it defines them as a string.
When I record them like $a = (int) $value It drops after '.' and record it as "1" "1" "1"...
How can I transform it to decimal values?
I need to sum up all values and I should transform them to decimal to do this.
When you cast a value to an integer its is no decimal number, decimal numbers are of type double. So cast it to double should work.
$a = (double) $value;
<?php echo number_format($value,2,'.','');?>
Integer values are not using ., these are double or float values, try
$a = (double) $value;// or $a = (float) $value;
After addition you should use number_format for formatting.

How do I convert a string to a number in PHP?

I want to convert these types of values, '3', '2.34', '0.234343', etc. to a number. In JavaScript we can use Number(), but is there any similar method available in PHP?
Input Output
'2' 2
'2.34' 2.34
'0.3454545' 0.3454545
You don't typically need to do this, since PHP will coerce the type for you in most circumstances. For situations where you do want to explicitly convert the type, cast it:
$num = "3.14";
$int = (int)$num;
$float = (float)$num;
There are a few ways to do so:
Cast the strings to numeric primitive data types:
$num = (int) "10";
$num = (double) "10.12"; // same as (float) "10.12";
Perform math operations on the strings:
$num = "10" + 1;
$num = floor("10.1");
Use intval() or floatval():
$num = intval("10");
$num = floatval("10.1");
Use settype().
To avoid problems try intval($var). Some examples:
<?php
echo intval(42); // 42
echo intval(4.2); // 4
echo intval('42'); // 42
echo intval('+42'); // 42
echo intval('-42'); // -42
echo intval(042); // 34 (octal as starts with zero)
echo intval('042'); // 42
echo intval(1e10); // 1410065408
echo intval('1e10'); // 1
echo intval(0x1A); // 26 (hex as starts with 0x)
echo intval(42000000); // 42000000
echo intval(420000000000000000000); // 0
echo intval('420000000000000000000'); // 2147483647
echo intval(42, 8); // 42
echo intval('42', 8); // 34
echo intval(array()); // 0
echo intval(array('foo', 'bar')); // 1
?>
In whatever (loosely-typed) language you can always cast a string to a number by adding a zero to it.
However, there is very little sense in this as PHP will do it automatically at the time of using this variable, and it will be cast to a string anyway at the time of output.
Note that you may wish to keep dotted numbers as strings, because after casting to float it may be changed unpredictably, due to float numbers' nature.
Instead of having to choose whether to convert the string to int or float, you can simply add a 0 to it, and PHP will automatically convert the result to a numeric type.
// Being sure the string is actually a number
if (is_numeric($string))
$number = $string + 0;
else // Let the number be 0 if the string is not a number
$number = 0;
Yes, there is a similar method in PHP, but it is so little known that you will rarely hear about it. It is an arithmetic operator called "identity", as described here:
Aritmetic Operators
To convert a numeric string to a number, do as follows:
$a = +$a;
If you want get a float for $value = '0.4', but int for $value = '4', you can write:
$number = ($value == (int) $value) ? (int) $value : (float) $value;
It is little bit dirty, but it works.
You can use:
(int)(your value);
Or you can use:
intval(string)
In PHP you can use intval(string) or floatval(string) functions to convert strings to numbers.
You can always add zero to it!
Input Output
'2' + 0 2 (int)
'2.34' + 0 2.34 (float)
'0.3454545' + 0 0.3454545 (float)
Just a little note to the answers that can be useful and safer in some cases.
You may want to check if the string actually contains a valid numeric value first and only then convert it to a numeric type (for example if you have to manipulate data coming from a db that converts ints to strings). You can use is_numeric() and then floatval():
$a = "whatever"; // any variable
if (is_numeric($a))
var_dump(floatval($a)); // type is float
else
var_dump($a); // any type
Here is the function that achieves what you are looking for. First we check if the value can be understood as a number, if so we turn it into an int and a float. If the int and float are the same (e.g., 5 == 5.0) then we return the int value. If the int and float are not the same (e.g., 5 != 5.3) then we assume you need the precision of the float and return that value. If the value isn't numeric we throw a warning and return null.
function toNumber($val) {
if (is_numeric($val)) {
$int = (int)$val;
$float = (float)$val;
$val = ($int == $float) ? $int : $float;
return $val;
} else {
trigger_error("Cannot cast $val to a number", E_USER_WARNING);
return null;
}
}
If you want the numerical value of a string and you don't want to convert it to float/int because you're not sure, this trick will convert it to the proper type:
function get_numeric($val) {
if (is_numeric($val)) {
return $val + 0;
}
return 0;
}
Example:
<?php
get_numeric('3'); // int(3)
get_numeric('1.2'); // float(1.2)
get_numeric('3.0'); // float(3)
?>
Source: https://www.php.net/manual/en/function.is-numeric.php#107326
I've been reading through answers and didn't see anybody mention the biggest caveat in PHP's number conversion.
The most upvoted answer suggests doing the following:
$str = "3.14"
$intstr = (int)$str // now it's a number equal to 3
That's brilliant. PHP does direct casting. But what if we did the following?
$str = "3.14is_trash"
$intstr = (int)$str
Does PHP consider such conversions valid?
Apparently yes.
PHP reads the string until it finds first non-numerical character for the required type. Meaning that for integers, numerical characters are [0-9]. As a result, it reads 3, since it's in [0-9] character range, it continues reading. Reads . and stops there since it's not in [0-9] range.
Same would happen if you were to cast to float or double. PHP would read 3, then ., then 1, then 4, and would stop at i since it's not valid float numeric character.
As a result, "million" >= 1000000 evaluates to false, but "1000000million" >= 1000000 evaluates to true.
See also:
https://www.php.net/manual/en/language.operators.comparison.php how conversions are done while comparing
https://www.php.net/manual/en/language.types.string.php#language.types.string.conversion how strings are converted to respective numbers
In addition to Boykodev's answer I suggest this:
Input Output
'2' * 1 2 (int)
'2.34' * 1 2.34 (float)
'0.3454545' * 1 0.3454545 (float)
Only multiply the number by 1 so that the string is converted to type number.
//String value
$string = "5.1"
if(is_numeric($string)){
$numeric_string = $string*1;
}
Alright so I just ran into this issue. My problem is that the numbers/strings in question having varying numbers of digits. Some have no decimals, others have several. So for me, using int, float, double, intval, or floatval all gave me different results depending on the number.
So, simple solution... divide the string by 1 server-side. This forces it to a number and retains all digits while trimming unnecessary 0's. It's not pretty, but it works.
"your number string" / 1
Input Output
"17" 17
"84.874" 84.874
".00234" .00234
".123000" .123
"032" 32
Here is a function I wrote to simplify things for myself:
It also returns shorthand versions of boolean, integer, double and real.
function type($mixed, $parseNumeric = false)
{
if ($parseNumeric && is_numeric($mixed)) {
//Set type to relevant numeric format
$mixed += 0;
}
$t = gettype($mixed);
switch($t) {
case 'boolean': return 'bool'; //shorthand
case 'integer': return 'int'; //shorthand
case 'double': case 'real': return 'float'; //equivalent for all intents and purposes
default: return $t;
}
}
Calling type with parseNumeric set to true will convert numeric strings before checking type.
Thus:
type("5", true) will return int
type("3.7", true) will return float
type("500") will return string
Just be careful since this is a kind of false checking method and your actual variable will still be a string. You will need to convert the actual variable to the correct type if needed. I just needed it to check if the database should load an item id or alias, thus not having any unexpected effects since it will be parsed as string at run time anyway.
Edit
If you would like to detect if objects are functions add this case to the switch:
case 'object': return is_callable($mixed)?'function':'object';
$a = "10";
$b = (int)$a;
You can use this to convert a string to an int in PHP.
I've found that in JavaScript a simple way to convert a string to a number is to multiply it by 1. It resolves the concatenation problem, because the "+" symbol has multiple uses in JavaScript, while the "*" symbol is purely for mathematical multiplication.
Based on what I've seen here regarding PHP automatically being willing to interpret a digit-containing string as a number (and the comments about adding, since in PHP the "+" is purely for mathematical addition), this multiply trick works just fine for PHP, also.
I have tested it, and it does work... Although depending on how you acquired the string, you might want to apply the trim() function to it, before multiplying by 1.
Late to the party, but here is another approach:
function cast_to_number($input) {
if(is_float($input) || is_int($input)) {
return $input;
}
if(!is_string($input)) {
return false;
}
if(preg_match('/^-?\d+$/', $input)) {
return intval($input);
}
if(preg_match('/^-?\d+\.\d+$/', $input)) {
return floatval($input);
}
return false;
}
cast_to_number('123.45'); // (float) 123.45
cast_to_number('-123.45'); // (float) -123.45
cast_to_number('123'); // (int) 123
cast_to_number('-123'); // (int) -123
cast_to_number('foo 123 bar'); // false
function convert_to_number($number) {
return is_numeric($number) ? ($number + 0) : FALSE;
}
You can use:
((int) $var) ( but in big number it return 2147483647 :-) )
But the best solution is to use:
if (is_numeric($var))
$var = (isset($var)) ? $var : 0;
else
$var = 0;
Or
if (is_numeric($var))
$var = (trim($var) == '') ? 0 : $var;
else
$var = 0;
Simply you can write like this:
<?php
$data = ["1","2","3","4","5"];
echo json_encode($data, JSON_NUMERIC_CHECK);
?>
There is a way:
$value = json_decode(json_encode($value, JSON_NUMERIC_CHECK|JSON_PRESERVE_ZERO_FRACTION|JSON_UNESCAPED_SLASHES), true);
Using is_* won't work, since the variable is a: string.
Using the combination of json_encode() and then json_decode() it's converted to it's "true" form. If it's a true string then it would output wrong.
$num = "Me";
$int = (int)$num;
$float = (float)$num;
var_dump($num, $int, $float);
Will output: string(2) "Me" int(0) float(0)
Now we are in an era where strict/strong typing has a greater sense of importance in PHP, I use json_decode:
$num = json_decode('123');
var_dump($num); // outputs int(123)
$num = json_decode('123.45');
var_dump($num); // outputs float(123.45)
You can change the data type as follows
$number = "1.234";
echo gettype ($number) . "\n"; //Returns string
settype($number , "float");
echo gettype ($number) . "\n"; //Returns float
For historical reasons "double" is returned in case of a float.
PHP Documentation
If you don't know in advance if you have a float or an integer,
and if the string may contain special characters (like space, €, etc),
and if it may contain more than 1 dot or comma,
you may use this function:
// This function strip spaces and other characters from a string and return a number.
// It works for integer and float.
// It expect decimal delimiter to be either a '.' or ','
// Note: everything after an eventual 2nd decimal delimiter will be removed.
function stringToNumber($string) {
// return 0 if the string contains no number at all or is not a string:
if (!is_string($string) || !preg_match('/\d/', $string)) {
return 0;
}
// Replace all ',' with '.':
$workingString = str_replace(',', '.', $string);
// Keep only number and '.':
$workingString = preg_replace("/[^0-9.]+/", "", $workingString);
// Split the integer part and the decimal part,
// (and eventually a third part if there are more
// than 1 decimal delimiter in the string):
$explodedString = explode('.', $workingString, 3);
if ($explodedString[0] === '') {
// No number was present before the first decimal delimiter,
// so we assume it was meant to be a 0:
$explodedString[0] = '0';
}
if (sizeof($explodedString) === 1) {
// No decimal delimiter was present in the string,
// create a string representing an integer:
$workingString = $explodedString[0];
} else {
// A decimal delimiter was present,
// create a string representing a float:
$workingString = $explodedString[0] . '.' . $explodedString[1];
}
// Create a number from this now non-ambiguous string:
$number = $workingString * 1;
return $number;
}
All suggestions lose the numeric type.
This seems to me a best practice:
function str2num($s){
// Returns a num or FALSE
$return_value = !is_numeric($s) ? false : (intval($s)==floatval($s)) ? intval($s) :floatval($s);
print "\nret=$return_value type=".gettype($return_value)."\n";
}
//Get Only number from string
$string = "123 Hello Zahid";
$res = preg_replace("/[^0-9]/", "", $string);
echo $res."<br>";
//Result 123

A function to get the smaller number

I have 2 variables each containing a number (integer). I would like to sort them to have the lowest number first and the second largest. For example:
$sortedVar = getSmaller(45, 62); // Will return 45
$sortedVar = getSmaller(87, 23); // Will return 23
Do you see what I want to do? Can you help me please?
Thanks :)
http://php.net/manual/en/function.min.php
min — Find lowest value..
If the first and only parameter is an array, min() returns the lowest value in that array. If at least two parameters are provided, min() returns the smallest of these values.
Note:
Values of different types will be compared using the standard comparison rules. For instance, a non-numeric string will be compared to an integer as though it were 0, but multiple non-numeric string values will be compared alphanumerically. The actual value returned will be of the original type with no conversion applied.
Caution
Be careful when passing arguments with mixed types values because min() can produce unpredictable results...
Use min() which supports any number of arguments as well as arrays.
$smallest = min(1,2); //returns 1
$smallest = min(4,3,2); //returns 2
$smallest = min(array(5,4)) //returns 4
function getSmaller($a, $b) {
return $a < $b ? $a : $b;
}
In plain english, if $a is smaller than $b, then return $a, else return $b.
Or as others pointed out, there's also a function for that, called min().
$sortedVar = $a < $b ? $a : $b;

Categories