3

MySQL data imoprt mongo database.

price float(15,2) in mysql, mongo is not float(15,2).

I want to Determine a var $price have two decimal places.

eg. 100.00 is right, 100 or 100.0 is wrong.

eg.1

$price = 100.00;

$price have two decimal, it's right.

eg.2

$price = 100.0;

$price have not two decimal, it's wrong.

Leandro Bardelli
  • 10,561
  • 15
  • 79
  • 116
jingyu
  • 115
  • 2
  • 13
  • The number of decimal places in a floating-point number is really down to formatting for display. Can you explain what you're actually trying to do? – Phil Nov 07 '14 at 01:58
  • Have you tried the answer I left for you? You did not leave feedback under it, whether it worked for you or not. – Funk Forty Niner Nov 11 '14 at 13:56
  • @jingyu Hello, do you want to display any price value with two numbers after decimal point in PHP? Let me know. Maybe i will be able to help you out. Regards – William Francis Gomes Nov 16 '14 at 04:00
  • don't use FLOAT to store prices, floating-point numbers may lose precision and they may produce unexpected results. Better to use DECIMAL. – fthiella Nov 16 '14 at 18:19

6 Answers6

6

I like to use Regular Expressions to do these things

function validateTwoDecimals($number)
{
   if(preg_match('/^[0-9]+\.[0-9]{2}$/', $number))
     return true;
   else
     return false;
}

(Thanks to Fred-ii- for the corrections)

Leandro Bardelli
  • 10,561
  • 15
  • 79
  • 116
  • 4
    You shouldn't use `ereg` it's deprecated. http://php.net/manual/en/function.ereg.php – Funk Forty Niner Nov 07 '14 at 02:07
  • I'm not sure if its the correct solution, I think my php is a bit obsolete now :S – Leandro Bardelli Nov 07 '14 at 02:09
  • 2
    Actually, you're missing the delimiters. Should probably be `preg_match('/^[0-9]+\.[0-9]{2}$/'` as per one example http://stackoverflow.com/a/1374920/ – Funk Forty Niner Nov 07 '14 at 02:12
  • What a shame on me, @Fred-ii-. I totally would vote up your answer if you make it, is really yours :! – Leandro Bardelli Nov 07 '14 at 02:13
  • 2
    It's fine Leandro, am just here to assist. +1 – Funk Forty Niner Nov 07 '14 at 02:13
  • I fiddle it and it's fine – Leandro Bardelli Nov 07 '14 at 02:27
  • It's only me, or there's something you're not taking in the calculations? Floating numbers does not have decimal places, it's only matter of rounding up/down, if you round to 2 decimals, you will have at most 2 decimal places, but if you round to 10 decimal places, you might end up with something like 9.0000000001 or 8.9999999999 So first of all, if the SQL is really storing floating values, then the question can not be answered ... In this case first he have to round to some amount of decimals, and check if that value is correct. but in this case, 100.10 is not a valid output ... – Gipsz Jakab Nov 07 '14 at 04:16
4

Everybody is dancing around the fact that floating point numbers don't have a number of decimal places in their internal representation. i.e. in float 100 == 100.0 == 100.00 == 100.000 and are all represented by the same number, effectively 100 and is stored that way.

The number of decimal places in this example only has a context when the number is represented as a string. In which case any string function that counts the number of digits trailing the decimal point could be used to check.

3
number_format($price, $numberOfDecimalDigits) === $price;

or

strrpos($price, '.') === strlen($price) - 1 - $numberOfDecimalDigits;

Trivia: $price should not be called a "float variable". This is a string that happens to represent a float value. 100.00 as a float has zero decimal digits, and 100.00 === 100 as float :

$price = 100.00;
echo $price; // output: 100
$price2 = (float)100;
echo $price === $price2; // ouput: 1
RandomSeed
  • 29,301
  • 6
  • 52
  • 87
2

In order for this to work, the number will need to be wrapped in quotes.

With the many scripts I've tested, using $price = 100.00; without quotes did not work, while $price = 100.10; did, so this is as best as it gets.

<?php 
$number = '100.00';
echo $number.'<br>';
$count = explode('.',$number);

echo 'The number of digits after the decimal point is: ' . strlen($count[1]);

if(strlen($count[1]) == 2){
echo "<br>";
echo "There is 2 decimal points.";
}

else{
echo "<br>";
echo "There is not 2 decimal points.";
}
Funk Forty Niner
  • 74,450
  • 15
  • 68
  • 141
  • This is brilliant, I always tried with 123.45 and double quotes. – Leandro Bardelli Nov 07 '14 at 03:59
  • @Leandro Thanks Leandro. It took me a while, but I managed to get it working. I hope the OP isn't relying on **not** using quotes around the number, otherwise using `.00` will not work without quotes. – Funk Forty Niner Nov 07 '14 at 04:00
  • Passing in a price of 100.00.00 will also pass via this code. You should include a check to ensure that the size of the array after exploding is 2. – Dave O'Dwyer Mar 05 '15 at 10:26
1

After you format the value, you can check with simply splitting the value as string into 2 parts, for example with explode ...

$ex=explode('.',$in,2); if (strlen($ex[1])==2) 
{
 // true
}
else
{
 // false
}

But again, as i've commented already, if you really have floating input, this is just not a reliable way, as floating numbers are without set decimal places, even if they appears so because of the rounding at the float=>string conversion

What you can do, if you really have floating numbers and wish to have xxx.yy format numbers:

1) convert float to string using round($x,2), so it will round to 2 decimal places. 2) explode the number as i've described, and do the following:

while (strlen($ex[1]<2)) {$ex[1].='0';}
$number=implode('.',$ex);
Gipsz Jakab
  • 433
  • 3
  • 9
1

I would use the following function for that:

function isFloatWith2Decimals($number) {
    return (bool) preg_match('/^(?:[1-9]{1}\d*|0)\.\d{2}$/', $number);
}

This will also check if you have only one leading 0 so number like 010.23 won't be considered as valid whereas number like 0.23 will.

And if you don't care about leading 0 you could use simpler method:

function isFloatWith2Decimals($number) {
    return (bool) preg_match('/^\d+\.\d{2}$/', $number);
}

Of course numbers need to be passed as string - if you pass 100.00 won't be considered as true, whereas '100.00' will

Marcin Nabiałek
  • 109,655
  • 42
  • 258
  • 291