-1

I have a variable that I would like to calculate the percentage of and set as a new variable.

This is how I was trying it but I'm getting an error.

$amount = $_POST['amount'];
$newamount = $amount*0.05;

But I am getting an error:

Fatal error: `Uncaught TypeError: Unsupported operand types: string * float in C:\xampp\htdocs\...

$_POST['amount'] is a dollar amount with symbol and 2 decimals like "$12.00".

What am I doing wrong?

IMSoP
  • 89,526
  • 13
  • 117
  • 169
  • `var_dump($amount);` what does it contain? Make sure it's a straight number with no commas or dollar signs. – aynber Jun 18 '21 at 12:55
  • `$_POST` is an array of ***strings***. Try [casting](https://www.php.net/manual/en/language.types.type-juggling.php#language.types.typecasting) it like `$amount = (int)$_POST['amount'];` – ciekals11 Jun 18 '21 at 12:56
  • @aynber its a dollar amount with symbol and 2 decimals like $12.00 – McChris_ Made_It Jun 18 '21 at 12:57
  • 1
    You'll need to strip out the $ before doing any arithmetic with it. – duncan Jun 18 '21 at 12:58

4 Answers4

2

Another way to make sure you always have an actual number is to strip out all of the non-numerical characters. This helps if $amount becomes $12,345.67

$amount = preg_replace("/[^0-9.-]/", '', $_POST['amount']);
aynber
  • 22,380
  • 8
  • 50
  • 63
1

Cast your $amount to int/float:


if (isset($_POST['amount'])) {
    $amount = intval($_POST['amount']);

    $newamount = $amount * 0.5;
}

To parse your currency depending on locale you can use NumerbFormatter (requires php_intl extension):

$_POST['amount'] = '$12.00';

//----

$amount = $_POST['amount'];

$fmt = new NumberFormatter('en_US', NumberFormatter::CURRENCY);

$newamount = $fmt->parseCurrency($amount, $currency) * 0.5;

Justinas
  • 41,402
  • 5
  • 66
  • 96
1

Assuming $_POST['amount'] looks like a number but is somehow being interpreted as a string, you maybe need to cast it to be a number:

$newamount= (float) $amount * 0.05;

Actually even if $amount were "1.23", the above line would work; no need to cast it. The problem is $amount = $12.00;

In which case, I'd suggest remove the first character. If you know it's always $ you can use ltrim to strip off any leading characters that are $

$amount = ltrim($_POST['amount'], '$');

If it could be one of several different currency symbols, e.g. you know it's always going to be one of £, $ or €, then you can use that like:

$amount = ltrim($_POST['amount'], '$£€');
duncan
  • 31,401
  • 13
  • 78
  • 99
0

PHP doesn't know what "dollars" are. When it sees "$12.00", it doesn't know that the dollar sign is separate, and to treat the rest as a number. As far as PHP is concerned, asking for "$12.00" * 0.05 is no different from asking for "$$$12.00$$$" * 0.05, or "potato" * 0.05.

So you have two options:

  • Change the form so that the value submitted is only numbers. If it's entered by the user, write some validation code that checks it is just a number, like if ( ! preg_match('/^\d+\.\d{2}$/', $_POST['amount']) ) { show_wrong_amount_error_message(); }
  • Strip the "$" off the front before processing it, using Duncan's suggestion of $amount = ltrim($_POST['amount'], '$'); or aynba's suggestion of $amount = preg_replace("/[^0-9.-]/", '', $_POST['amount']);

Or you could combine the two: check that it has exactly a dollar sign, a number of dollars, and a number of cents; then discard the dollar sign and carry on:

if ( preg_match('/^\$(\d+\.\d{2})$/', $_POST['amount'], $matched_parts) ) { 
    $amount = (float)$matched_parts[1];
}
else {
    show_wrong_amount_error_message();
}

You should also consider handling money as an integer number of cents, not a floating point number of dollars, because floating point numbers are not precise. So you could adjust the above to give you the amount in cents instead:

if ( preg_match('/^\$(\d+)\.(\d{2})$/', $_POST['amount'], $matched_parts) ) { 
    $amount_cents = (int)$matched_parts[1] * 100 + (int)$matched_parts[2];
}
else {
    show_wrong_amount_error_message();
}
IMSoP
  • 89,526
  • 13
  • 117
  • 169