Jump to content

PHP calulate 2 array values

Go to solution Solved by C2dan88,

@Joveice What preg_match function are you using?

 

The array output shown by @mariushm is the result from preg_match_all

However the array output you have shown is the result from preg_match

 

If you are using preg_match_all then you need to do the multiplication on $matches[1][0]  and $matches[2][0]

I don't really understand what you are asking or trying to achieve. Could you be a little more descriptive in what you are making and why what you have written down doesn't work?

"We're all in this together, might as well be friends" Tom, Toonami.

 

mini eLiXiVy: my open source 65% mechanical PCB, a build log, PCB anatomy and discussing open source licenses: https://linustechtips.com/topic/1366493-elixivy-a-65-mechanical-keyboard-build-log-pcb-anatomy-and-how-i-open-sourced-this-project/

 

mini_cardboard: a 4% keyboard build log and how keyboards workhttps://linustechtips.com/topic/1328547-mini_cardboard-a-4-keyboard-build-log-and-how-keyboards-work/

Link to post
Share on other sites

1 minute ago, zwirek2201 said:

Is that what you're trying to achieve? 


$matches = array(1, 2);
foreach ($matches as &$value) {
    $value = $value * 1000;
}

If not, please edit your question with more information

This is exaclty what I'm trying to do, thanks!

 

3 minutes ago, Minibois said:

I don't really understand what you are asking or trying to achieve. Could you be a little more descriptive in what you are making and why what you have written down doesn't work?

It throws a error and says it's not allowed.

Back-end developer, electronics "hacker"

Link to post
Share on other sites

You can also use the array_walk (http://php.net/manual/en/function.array-walk.php) function

Usage:

$array = [2,3,4];

array_walk($array, function(&$item){
    /* Perform your action */
    $item = $item * 1000;
});

/*
    Result: 
    $array = [
        2000,
        3000,
        4000
    ]
*/

 

Business Management Student @ University St. Gallen (Switzerland)

HomeServer: i7 4930k - GTX 1070ti - ASUS Rampage IV Gene - 32Gb Ram

Laptop: MacBook Pro Retina 15" 2018

Operating Systems (Virtualised using VMware): Windows Pro 10, Cent OS 7

Occupation: Software Engineer

Link to post
Share on other sites

8 minutes ago, Joveice said:

This is exaclty what I'm trying to do, thanks!

 

It throws a error and says it's not allowed.

Since (even though you received an answer) your code doesn't seem to have any error in it, I'm going to make a quick guess that your array contains 2 elements and you're trying to access second and third element (computers count from 0).


If following code does not throw an error, it means that you're trying to access the element $matches[2] while array only contains elements 0 and 1.

$matches[0] = ($matches[0] * 1000);
$matches[1] = ($matches[1] * 1000);


 

Try, fail, learn, repeat...

Link to post
Share on other sites

1 minute ago, zwirek2201 said:

Since (even though you received an answer) your code doesn't seem to have any error in it, I'm going to make a quick guess that your array contains 2 elements and you're trying to access second and third element (computers count from 0).


If following code does not throw an error, it means that you're trying to access the element $matches[2] while array only contains elements 0 and 1.


$matches[0] = ($matches[0] * 1000);
$matches[1] = ($matches[1] * 1000);


 

Yea it stil throws a error now when I tested my array again.

 

Fatal error: Uncaught Error: Unsupported operand types in *Filename* line *Shown under*
$value = ($value * 1000);

My array

matches => Array (
    [0] => /dev/sdd1      106541128 9787684  91318412
    [1] => 9787684
    [2] => 91318412
)

and I'm trying to multiply 1 and 2 by 1000 then add them togheter later so I get 3 numbers, 1 and 2 multiplayed by 1000 and 1 and 2 multiplayed by 1000 then added.

 

might the reason for why this breaks be that it says the array is a string and not a int?

Back-end developer, electronics "hacker"

Link to post
Share on other sites

5 minutes ago, Joveice said:

Yea it stil throws a error now when I tested my array again.

 


Fatal error: Uncaught Error: Unsupported operand types in *Filename* line *Shown under*

$value = ($value * 1000);

My array


matches => Array (
    [0] => /dev/sdd1      106541128 9787684  91318412
    [1] => 9787684
    [2] => 91318412
)

and I'm trying to multiply 1 and 2 by 1000 then add them togheter later so I get 3 numbers, 1 and 2 multiplayed by 1000 and 1 and 2 multiplayed by 1000 then added.

 

might the reason for why this breaks be that it says the array is a string and not a int?

Php usually handles string to int conversion on its own, but the error would suggest that values of the $matches array are neither int nor string values. This kind of error would occur if the values were of a different type (such as array). Your best bet would be:
Trying to cast the value to int

$value = (int)$value * 1000;

and if that not helps, 
checking if values are for sure string or integer and not for example an array.

 

Try, fail, learn, repeat...

Link to post
Share on other sites

27 minutes ago, Joveice said:

might the reason for why this breaks be that it says the array is a string and not a int?

Yes.

 

I don't really get what you want. You can filter the array to have only int values.

$array = array_filter(['string',10,20],'is_int');
/* 
Result:
[
    1 => 10,
    2 => 20
]
*/

Or if you want to keep the string maybe something like this

$array = [
    'string',
    1,
    2,
    3,
    4
];

/* Multiply them */
array_walk($array,function(&$item){
    /* multiply if is_int */
    if(is_int($item))
        $item = $item*1000;
});

/* Add Sum, only add Integers together! This ensures only int values are summed up */
$sum = array_sum( array_filter($array,'is_int') );

/* Result:
    $array = ['string',1000,2000,3000,4000];
    $sum = 10000;
*/

 

Business Management Student @ University St. Gallen (Switzerland)

HomeServer: i7 4930k - GTX 1070ti - ASUS Rampage IV Gene - 32Gb Ram

Laptop: MacBook Pro Retina 15" 2018

Operating Systems (Virtualised using VMware): Windows Pro 10, Cent OS 7

Occupation: Software Engineer

Link to post
Share on other sites

2 minutes ago, zwirek2201 said:

Php usually handles string to int conversion on its own, but the error would suggest that values of the $matches array are neither int nor string values. This kind of error would occur if the values were of a different type (such as array). Your best bet would be:
Trying to cast the value to int


$value = (int)$value * 1000;

and if that not helps, 
checking if values are for sure string or integer and not for example an array.

 

I will try,

 

1 minute ago, leodaniel said:

Yes.

 

I don't really get what you want. You can filter the array to have only int values.


$array = array_filter(['string',10,20],'is_int');
/* 
Result:
[
    1 => 10,
    2 => 20
]
*/

Or if you want to keep the string maybe something like this


$array = [
    'string',
    1,
    2,
    3,
    4
];

/* Multiply them */
array_walk($array,function(&$item){
    /* multiply if is_int */
    if(is_int($item))
        $item = $item*1000;
});

/* Add Sum, only add Integers together! This ensures only int values are summed up */
$sum = array_sum( array_filter($array,'is_int') );

/* Result:
    $array = ['string',1000,2000,3000,4000];
    $sum = 10000;
*/

 

The array is created by preg_match

Back-end developer, electronics "hacker"

Link to post
Share on other sites

6 minutes ago, Joveice said:

The array is created by preg_match

preg_match will return an $match array in which $match[0] is the full text of your match!

/* Simply unset it */
unset($match[0]);

 

Edited by leodaniel
added unset code

Business Management Student @ University St. Gallen (Switzerland)

HomeServer: i7 4930k - GTX 1070ti - ASUS Rampage IV Gene - 32Gb Ram

Laptop: MacBook Pro Retina 15" 2018

Operating Systems (Virtualised using VMware): Windows Pro 10, Cent OS 7

Occupation: Software Engineer

Link to post
Share on other sites

4 minutes ago, leodaniel said:

preg_match will return an $match array in which $match[0] is the full text of your match!

Thats why I'm not using that

$variable[0] = $matches[1];
$variable[1] = $matches[2];

see, no $matches[0]

Back-end developer, electronics "hacker"

Link to post
Share on other sites

2 minutes ago, Joveice said:

Thats why I'm not using that


$variable[0] = $matches[1];
$variable[1] = $matches[2];

see, no $matches[0]

Okey so everything is fine?

/* just unset the match[0] */
unset($match[0]);

 

Business Management Student @ University St. Gallen (Switzerland)

HomeServer: i7 4930k - GTX 1070ti - ASUS Rampage IV Gene - 32Gb Ram

Laptop: MacBook Pro Retina 15" 2018

Operating Systems (Virtualised using VMware): Windows Pro 10, Cent OS 7

Occupation: Software Engineer

Link to post
Share on other sites

5 minutes ago, leodaniel said:

Okey so everything is fine?


/* just unset the match[0] */
unset($match[0]);

 

Nah, still issues.

 

// grab data
unset($matches);
$re = '/^[\/dev\/sdd1]+\s+[0-9]+\s+([0-9]+)\s+([0-9]+)/m';
$str = '/dev/sdd1      106541128 9787684  91318412  10% /';

$data = array();
$data[] = preg_match_all($re, $str, $matches);

if ($stmt = $mysqli->prepare('INSERT INTO status_storage_pools (pname, totalspace, totalused) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE totalspace=VALUES(totalspace), totalused=VALUES(totalused)')) {

    /* bind parameters for markers */
    unset($matches[0]);
    $matches[1] = (int)$matches[1] * 1000;
    $matches[2] = (int)$matches[2] * 1000;

    $variable = ((int)$matches[1] + (int)$matches[2]);
    var_dump($variable);
    var_dump($matches);
    $name = 'OS';
    $stmt->bind_param('sss', $name, $variable, $matches[1]);
    unset($variable);

    /* execute query */
    $stmt->execute();

    /* close statement */
    $stmt->close();
} else {
    /* close connection */
    $mysqli->close();
    echo 'ERROR';
    exit();
}

Whole code.

Back-end developer, electronics "hacker"

Link to post
Share on other sites

6 hours ago, Joveice said:

Yea it stil throws a error now when I tested my array again.

 


Fatal error: Uncaught Error: Unsupported operand types in *Filename* line *Shown under*

$value = ($value * 1000);

My array


matches => Array (
    [0] => /dev/sdd1      106541128 9787684  91318412
    [1] => 9787684
    [2] => 91318412
)

and I'm trying to multiply 1 and 2 by 1000 then add them togheter later so I get 3 numbers, 1 and 2 multiplayed by 1000 and 1 and 2 multiplayed by 1000 then added.

 

might the reason for why this breaks be that it says the array is a string and not a int?

 

Jesus so many advices from easy to ridiculously complicated.

 

You can find the number of records in the array using the function count()  - for example, in your example above count($matches) will return 3.

 

If an array has integer keys for every record ( 0,1,2,3) , you can simply walk the array with a simple for  :


 

$recordcount = count($matches);
for ($i = 0; $i < $recordcount ; $i++) {
 $matches[$i] = $matches[$i] * 1000;
}

 

If you know the first record in the array is not a number of you don't want to multiply it by 1000, just initialize i in the array with 1:


 

$recordcount = count($matches);
for ($i = 1; $i < $recordcount ; $i++) {
 $matches[$i] = $matches[$i] * 1000;
}

If you don't know which records are numbers and which are strings, then you could determine it by using functions like is_int()  or ctype_digit or is_numeric ( is_numeric will also say the value is a number if it's a string that can be "translated" into a number, like 0xA0 (up to php v7) which is 160 in hexadecimal, or 1.35e2 which is scientific notation for 135 (1.35 multiplied by 1 followed by 2 zeroes). is_int() strictly checks that the value is a 32bit or 64 bit integer number, no decimals, nothing.  ctype_digit is even more restrictive, it allows only digits 0 to 9 in the string, any other character and the function returns false.

 

$recordcount = count($matches);

for ($i = 0; $i < $recordcount ; $i++) {
	if (ctype_digit($matches[$i]) == TRUE) {
		$matches[$i] = $matches[$i] * 1000;
	}
}

 

If you're not sure if the array has all numeric keys, or there may be holes in the record keys  you can go through it using foreach ... for example let's say you have this array :

 

$matches = array ( 'list' = > 100 , 0=> 12345 , 45 => 'george');

so you'd walk through it like this :

 

// if you don't care about the key of each record, you can omit it.. 
// for example if you just want to print the records on screen

foreach ($matches as $key => $content) {
	if ($ctype_digit($matches[$key]) == TRUE ) $matches[$key] = $content * 1000;
}

// You can also have the value by reference instead of value by adding a & in front of variable in 
// which case if you do something with that variable, the value is automatically updated in the array

foreach ($matches as $key => &$content) {
	if ($ctype_digit($matches[$key]) == TRUE ) $content = $content * 1000;
}

Variables by reference : http://php.net/manual/en/language.references.pass.php

 

You can also add records to an array, in your case you can simply add to that array :

 

$matches[3] = $matches[1] * 1000;
$matches[4] = $matches[2] * 1000;
$matches[5] = $matches[3] + $matches[4];

instead of overwriting the original values, so that maybe you'd have the old data and the new information you need.

 

Link to post
Share on other sites

5 hours ago, mariushm said:

 

Jesus so many advices from easy to ridiculously complicated.

 

You can find the number of records in the array using the function count()  - for example, in your example above count($matches) will return 3.

 

If an array has integer keys for every record ( 0,1,2,3) , you can simply walk the array with a simple for  :


 


$recordcount = count($matches);
for ($i = 0; $i < $recordcount ; $i++) {
 $matches[$i] = $matches[$i] * 1000;
}

 

If you know the first record in the array is not a number of you don't want to multiply it by 1000, just initialize i in the array with 1:


 


$recordcount = count($matches);
for ($i = 1; $i < $recordcount ; $i++) {
 $matches[$i] = $matches[$i] * 1000;
}

If you don't know which records are numbers and which are strings, then you could determine it by using functions like is_int()  or ctype_digit or is_numeric ( is_numeric will also say the value is a number if it's a string that can be "translated" into a number, like 0xA0 (up to php v7) which is 160 in hexadecimal, or 1.35e2 which is scientific notation for 135 (1.35 multiplied by 1 followed by 2 zeroes). is_int() strictly checks that the value is a 32bit or 64 bit integer number, no decimals, nothing.  ctype_digit is even more restrictive, it allows only digits 0 to 9 in the string, any other character and the function returns false.

 


$recordcount = count($matches);

for ($i = 0; $i < $recordcount ; $i++) {
	if (ctype_digit($matches[$i]) == TRUE) {
		$matches[$i] = $matches[$i] * 1000;
	}
}

 

If you're not sure if the array has all numeric keys, or there may be holes in the record keys  you can go through it using foreach ... for example let's say you have this array :

 


$matches = array ( 'list' = > 100 , 0=> 12345 , 45 => 'george');

so you'd walk through it like this :

 


// if you don't care about the key of each record, you can omit it.. 
// for example if you just want to print the records on screen

foreach ($matches as $key => $content) {
	if ($ctype_digit($matches[$key]) == TRUE ) $matches[$key] = $content * 1000;
}

// You can also have the value by reference instead of value by adding a & in front of variable in 
// which case if you do something with that variable, the value is automatically updated in the array

foreach ($matches as $key => &$content) {
	if ($ctype_digit($matches[$key]) == TRUE ) $content = $content * 1000;
}

Variables by reference : http://php.net/manual/en/language.references.pass.php

 

You can also add records to an array, in your case you can simply add to that array :

 


$matches[3] = $matches[1] * 1000;
$matches[4] = $matches[2] * 1000;
$matches[5] = $matches[3] + $matches[4];

instead of overwriting the original values, so that maybe you'd have the old data and the new information you need.

 

This was quite informative, but it's still missing the key issue, my 2 number values in the array are strings and when I try to multiply them php throws a error and says

 

Fatal error: Uncaught Error: Unsupported operand types in *Filename* line *where I multiply*

Back-end developer, electronics "hacker"

Link to post
Share on other sites

All I can think of at a very brief look would be that you may have some data type conversion issue, because you're trying to multiply a large number by 1000, which would result in a number that's bigger than what an integer can hold (231 for signed integer).

In your example, 91318412 x 1000 = 91'318'412'000 or 0x 0015 4300 62E0  , clearly above 0x FFFF FFFF which could be stored in an unsigned integer.

 

In PHP integers are 32 bit unless you're using a php 7 64bit copy

 

I'd suggest using var_dump($matches); to see the exact contents of those elements in the array, just in case you may actually have some extra stuff like null characters or spaces.

Maybe even use functions like json_encode or serialize would be more helpful since these would encode the array in a portable format which would allow you to see the individual character/bytes in the array records.

 

It would help to know where is that $matches array obtained from.

Link to post
Share on other sites

14 minutes ago, mariushm said:

All I can think of at a very brief look would be that you may have some data type conversion issue, because you're trying to multiply a large number by 1000, which would result in a number that's bigger than what an integer can hold (231 for signed integer).

In your example, 91318412 x 1000 = 91'318'412'000 or 0x 0015 4300 62E0  , clearly above 0x FFFF FFFF which could be stored in an unsigned integer.

 

In PHP integers are 32 bit unless you're using a php 7 64bit copy

 

I'd suggest using var_dump($matches); to see the exact contents of those elements in the array, just in case you may actually have some extra stuff like null characters or spaces.

Maybe even use functions like json_encode or serialize would be more helpful since these would encode the array in a portable format which would allow you to see the individual character/bytes in the array records.

 

It would help to know where is that $matches array obtained from.

A litte longer up you can find a chunk off my code (that dosent work) which has the part it gets the data from, if it's too big how can I then multiply them? I'm not sure if it's 32 or 64 bit

Back-end developer, electronics "hacker"

Link to post
Share on other sites

In your source code above you have:

 

$re = '/^[\/dev\/sdd1]+\s+[0-9]+\s+([0-9]+)\s+([0-9]+)/m';
$str = '/dev/sdd1      106541128 9787684  91318412  10% /';

$data = array();
$data[] = preg_match_all($re, $str, $matches);

//var_dump($matches);  // <- uncomment to check the preg_ function result

 

 

your $matches array looks like this  - output of var_dump($matches)  :

 

array(3) {
  [0]=>
  array(1) {
    [0]=>
    string(42) "/dev/sdd1      106541128 9787684  91318412"
  }
  [1]=>
  array(1) {
    [0]=>
    string(7) "9787684"
  }
  [2]=>
  array(1) {
    [0]=>
    string(8) "91318412"
  }
}

 

so your first number is actually stored in $matches[1][0]  and your second number is stored as $matches[2][0]

 

ps. For such a simple string, i really don't see the point of using regular expressions. You could simply use explode() to split the string into multiple segments using space as separator (or tab, or both space and tab, function accepts an array of separators or a single separator) and then you could simply walk the array ignoring empty records.

 

 

 

Link to post
Share on other sites

22 minutes ago, mariushm said:

In your source code above you have:

 


$re = '/^[\/dev\/sdd1]+\s+[0-9]+\s+([0-9]+)\s+([0-9]+)/m';
$str = '/dev/sdd1      106541128 9787684  91318412  10% /';

$data = array();
$data[] = preg_match_all($re, $str, $matches);

//var_dump($matches);  // <- uncomment to check the preg_ function result

 

 

your $matches array looks like this  - output of var_dump($matches)  :

 


array(3) {
  [0]=>
  array(1) {
    [0]=>
    string(42) "/dev/sdd1      106541128 9787684  91318412"
  }
  [1]=>
  array(1) {
    [0]=>
    string(7) "9787684"
  }
  [2]=>
  array(1) {
    [0]=>
    string(8) "91318412"
  }
}

 

so your first number is actually stored in $matches[1][0]  and your second number is stored as $matches[2][0]

 

ps. For such a simple string, i really don't see the point of using regular expressions. You could simply use explode() to split the string into multiple segments using space as separator (or tab, or both space and tab, function accepts an array of separators or a single separator) and then you could simply walk the array ignoring empty records.

 

 

 

The array looks like this 

array(3) {
  [0]=> string(42) "/dev/sdd1      106541128 9787684  91318412"
  [1]=> string(7) "9787684"
  [2]=> string(8) "91318412"
}

Not like that.

 

I use regex because it's not going to be that reliable with explode, I just have a copy of the output I'm going to use as I'm not working on the linux machine this is going to be used.

Back-end developer, electronics "hacker"

Link to post
Share on other sites

@Joveice What preg_match function are you using?

 

The array output shown by @mariushm is the result from preg_match_all

However the array output you have shown is the result from preg_match

 

If you are using preg_match_all then you need to do the multiplication on $matches[1][0]  and $matches[2][0]

Link to post
Share on other sites

5 minutes ago, C2dan88 said:

@Joveice What preg_match function are you using?

 

The array output shown by @mariushm is the result from preg_match_all

However the array output you have shown is the result from preg_match

 

If you are using preg_match_all then you need to do the multiplication on $matches[1][0]  and $matches[2][0]

Ouch, that might be the issue, When I tested first I used preg_match then later I needed to match more then I used preg_match_all and I have forgotten to change back later when using the new script. And better in that is when I miss understand the var_dump as I don't see the array inside the array.

 

This is actually the issue, I changed back to preg_match and I tryed to multiply it by 1000 and it worked. Thanks! such a little mistake can damage that much :P

Back-end developer, electronics "hacker"

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×