Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 7 of 7
  1. #1
    Senior Coder timgolding's Avatar
    Join Date
    Aug 2006
    Location
    Southampton
    Posts
    1,519
    Thanks
    114
    Thanked 110 Times in 109 Posts

    floor(589.92 * 100)

    can anyone help me understand why

    PHP Code:
    <?php
    $mult 
    =  (589.92 100);
    echo 
    $mult;
    echo (
    floor($mult));

    // should display 5892 but displays 5891
    All i want to do is times 100 to an amount to eliminate the decimals.

    So if my total inc vat for my basket is 589.92 then timsing by 100 should give 58992. but it doesn't quite as the above code shows.

    I used to have

    PHP Code:
    if(str_replace(","""$grand_total) != round(str_replace(","""$grand_total),2))   
    {
                return 
    false;
    }   
    $this->amount floor(str_replace(","""$grand_total)*100); 
    This is wrong as often the amount is 1 penny less than grand total.

    Can i just times by 100. I want a check that the grand total is formatted correctly and i want the result to be an integer.

    Would this be correct
    PHP Code:
    $grand_total = (float)(preg_replace("/[^0-9\.]+/"""$grand_total));
    if(
    $grand_total != round($grand_total2))
       return 
    false;
    $this->amount round($grand_total 100); 
    You can not say you know how to do something, until you can teach it to someone else.

  • #2
    Senior Coder timgolding's Avatar
    Join Date
    Aug 2006
    Location
    Southampton
    Posts
    1,519
    Thanks
    114
    Thanked 110 Times in 109 Posts
    Or this

    PHP Code:
    // check the grand total is formated to two decimal places
    if($grand_total != round($grand_total2))
        return 
    false;
        
    // remove the .
    $this->amount preg_replace("/[^0-9]+/"""$grand_total); 
    This amount is only used as a hidden form value to post to the payments provider. So it can be a string.
    You can not say you know how to do something, until you can teach it to someone else.

  • #3
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,987
    Thanks
    4
    Thanked 2,660 Times in 2,629 Posts
    Its a float, not an int. Even though I cannot get the actual number to show, floats are by their very definition imprecise. The number you have when rounded to 40 significant digits is: 58991.9999999999927240423858165740966796875000 which since PHP typically binds to. . . 5 (or is it 8 maybe?) I believe it is with a string interpretation of a float, automatically rounds up.
    If you do not want to keep the decimals, than cast the results to an int. That will truncate them off without rounding. You haven't defined what is is you actually want though, so I don't know if that's it. Otherwise, you'll need to do *a lot* more work when it comes to verifying precision loss.
    Floats are a problem no matter what language you work in. Computation mathematics describes all the problems you get into when using numbers, and typically full number representation is far more useful than any double.
    PHP Code:
    header('HTTP/1.1 420 Enhance Your Calm'); 

  • #4
    Senior Coder timgolding's Avatar
    Join Date
    Aug 2006
    Location
    Southampton
    Posts
    1,519
    Thanks
    114
    Thanked 110 Times in 109 Posts
    Sorry I have a payments class a functions that has $grand_total as the input.
    In this function i want to achieve two things.
    - Verify that the grand total is formatted to 2 decimal places. It is in pence.
    - times by 100 and to strip off the decimal places. eg 2.40 becomes 240.


    Then i know what is being sent to the payments provider is correct.

    example

    PHP Code:
    function get_hash($oid$grand_total)
    {
            
    // check it is formatted to two decimal places??
            
    if($grand_total != round($grand_total2))
                return 
    false;
             
            
    // times by 100??   
            
    $this->amount preg_replace("/[^0-9]+/"""$grand_total);
     
    //

    Is this right?
    You can not say you know how to do something, until you can teach it to someone else.

  • #5
    Senior Coder timgolding's Avatar
    Join Date
    Aug 2006
    Location
    Southampton
    Posts
    1,519
    Thanks
    114
    Thanked 110 Times in 109 Posts
    On testing i found the above example had errors.
    The input variables couldn't be different variations of currency numbers.

    input variables and output i expect from the function.
    PHP Code:
     $grand_total 37.03// output "3703"
     
    $grand_total 37.2// output "3720"
     
    $grand_total 37// output "3700"
     
    $grand_total "37.03"// output "3703"
     
    $grand_total "37.2"// output "3720"
     
    $grand_total "37"// output "3700"
     
    $grand_total "45,456.00"// output false;
     
    $grand_total 45.645// output false;
     
    $grand_total "45.645"// output false;
     
    $grand_total = -45// output false;
     
    $grand_total true// output 100;
     
    $grand_total false// output false;
     
    $grand_total = array(); // output false;
     
    $grand_total = new object(); // output false; 
    Its a question of validating the input variable and making sure that the input variable is a positive currency value. It can be a float and integer or a correctly formatted string with no commas. But it must be to two decimal places.

    This is code i have so far.
    PHP Code:

    // test the number geater than zero and that its either float a int or a correctly formatted string.
    $valid_num false;
    if((
    is_float($grand_total) && $grand_total>0) || (is_int($grand_total) && $grand_total>0) || (!preg_match("/[^0-9\.]+/"$grand_total) && $grand_total>0)
        
    $valid_num true;

    // check that it is in pence. No extra decimals
    if(!$valid_num || $grand_total != round($grand_total2))
        return 
    false;

    // format the input to two decimal places but with no commas and the strip the dots effectively multiply by 100
    $this->amount preg_replace("/[^0-9]+/"""number_format($grand_total2".""")); 
    This is what i have so far. But this will except scientific notation and im not sure if i should be excepting something like
    PHP Code:
     $grand_total 1e7// output 1000000000; 
    I'm not sure if i should be excepting these values? I'm trying to find the most efficient way of doing this.
    You can not say you know how to do something, until you can teach it to someone else.

  • #6
    Super Moderator
    Join Date
    May 2002
    Location
    Perth Australia
    Posts
    4,040
    Thanks
    10
    Thanked 92 Times in 90 Posts
    why not format the total first b4 you test , then you know you are getting either 0 or a decimal value ...
    PHP Code:
    $val=number_format($val,2,'.','');
    if(
    $val 0){ ...etc
    resistance is...

    MVC is the current buzz in web application architectures. It comes from event-driven desktop application design and doesn't fit into web application design very well. But luckily nobody really knows what MVC means, so we can call our presentation layer separation mechanism MVC and move on. (Rasmus Lerdorf)

  • #7
    Senior Coder timgolding's Avatar
    Join Date
    Aug 2006
    Location
    Southampton
    Posts
    1,519
    Thanks
    114
    Thanked 110 Times in 109 Posts
    The problem i see with that formatting the number first. is when the input value is a string and has a comma. Or if the input has extra decimals

    e.g
    PHP Code:
    echo number_format("3,500.92",2,'.',''); // gives 3.00

    echo number_format(35.935,2,'.',''); // gives 35.94 
    I really want it to return false in these two instances.

    I came up with this test script
    PHP Code:

    <?php


    class myobject
    {
        public 
    $var false;
    }

     
    $test=array();
     
    $test[] = "5,300.93"// output false
     
    $test[] = 37.03// output "3703"
     
    $test[] = 37.2// output "3720"
     
    $test[] = 37// output "3700"
     
    $test[] = "37.03"// output "3703"
     
    $test[] = "37.2"// output "3720"
     
    $test[]= "37"// output "3700"
     
    $test[] = "45,456.00"// output false;
     
    $test[] = 45.645// output false;
     
    $test[] = "45.645"// output false;
     
    $test[] = -45// output false;
     
    $test[] = 1e7// output false;
     
    $test[] = true// output 100;
     
    $test[] = false// output false;
     
    $test[]= array(); // output false;
     
    $test[] = new myobject(); // output false;


    foreach($test as $grand_total)
    {
        
    var_dump($grand_total);
        
        
    $valid_num false;
        if((
    is_float($grand_total) || is_int($grand_total) || (is_string($grand_total) && !preg_match("/[^0-9\.]+/"$grand_total)))&& $grand_total>0)
            
    $valid_num true;
        
        if(!
    $valid_num || $grand_total != round($grand_total2))
        {    
            
    $amount false;
        }
        else
        {
            
    $amount preg_replace("/[^0-9]+/"""number_format($grand_total2"."""));
        }
        
    var_dump$amount);
        echo 
    "<br />";
    }

    ?>
    The output to this script is as follows.
    string(8) "5,300.93" bool(false)
    float(37.03) string(4) "3703"
    float(37.2) string(4) "3720"
    int(37) string(4) "3700"
    string(5) "37.03" string(4) "3703"
    string(4) "37.2" string(4) "3720"
    string(2) "37" string(4) "3700"
    string(9) "45,456.00" bool(false)
    float(45.645) bool(false)
    string(6) "45.645" bool(false)
    int(-45) bool(false)
    float(10000000) string(10) "1000000000"
    bool(true) bool(false)
    bool(false) bool(false)
    array(0) { } bool(false)
    object(myobject)#1 (1) { ["var"]=> bool(false) } bool(false)
    This seems to be giving the expected results. What I can't figure out is weather i should be excepting the input value as a scientific notation float.
    Should this return false. Also wondered if i can somehow be more efficient with the validation and multiplication process?
    You can not say you know how to do something, until you can teach it to someone else.


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •