Edit report at https://bugs.php.net/bug.php?id=65485&edit=1
ID: 65485 Comment by: stephane at it-asia dot com Reported by: stephane at it-asia dot com Summary: Cast gives different values in one way or the other Status: Not a bug Type: Bug Package: *General Issues Operating System: Windows 8 & Mint Maya PHP Version: 5.4.18 Block user comment: N Private report: N New Comment: OK Thanks for you answer, your time, and everything you do for us. S.L. Previous Comments: ------------------------------------------------------------------------ [2013-08-20 17:35:23] [email protected] Always always always write all apps that deal with money using only integers. You never work with 17.99 you work with 1799 and only at display time do you add a decimal place. All internal manipulation is done using integers without any precision loss. ------------------------------------------------------------------------ [2013-08-20 16:40:01] stephane at it-asia dot com OK, you the boss. >This is trivial to do in user space. So what's your recommendation there? ------------------------------------------------------------------------ [2013-08-20 15:19:55] [email protected] var_dump() is giving you the real value based on your precision setting. If you add ini_set('precision',32); to the top of your test script, you will see: float(3947.9999999999995452526491135359) float(3948) int(3947) int(3948) And this is exactly the same as C and Python. And no, there won't be a money type in PHP. This is trivial to do in user space. ------------------------------------------------------------------------ [2013-08-20 13:44:38] stephane at it-asia dot com Hi Rasmus Good to find you here. I understand you follow the C engine. But in C , you have 39.48*100 = 3947.9999999999995 and in Python, you have 39.48*100 = 3947 when PHP shows 3948 . PHP makes a few more things than that. It is not exactly the same. More, when I make tests in the php.ini to increase the precision to 20, the float â string gives 3947.9999999999995453 (and 3947.99999999999954525264911353588104248046875 for a precision of 100) And the vardump doesn't really give the real full value : it is confusing. var_dump (39.48 * 100) => float(3948) => this is not the real value. Better example: $d1 = 39.48 * 100; $d2 = 3948.0; $i1 = (int) $d1; $i2 = (int) $d2; var_dump($d1); var_dump($d2); var_dump($i1); var_dump($i2); it returns float(3948) float(3948) int(3947) int(3948) it should return float(3947.99999999999954525264911353588104248046875) float(3948) int(3947) int(3948) Can we have a more precise vardump, so we know exactly what happens? I lost time because of that. If the vardump gave me 3947.99999999999954525264911353588104248046875 this morning, I would have understood directly what happened. But it gave me 3948, and it is not the real value. I was accustomed to see PHP to provide easy and direct solutions. I don't know why, but I was totally convinced we found a way to go over this kind of problems. Obviously, talk to any developer around you, nobody never expects to see 3948 become 3947 after a cast when a decimal number was involved 100 lines before. In VB6, the result is always 3948 (even for double â int casting ), and they have a currency type. SQL server created a "money" type to avoid this kind of problems ( http://technet.microsoft.com/en-us/library/ms179882.aspx ). I hate saying that, but these guys found solutions when we still didn't. Rasmus, can I suggest to consider a new type for âmoneyâ treatments? So we will still have the normal int and float that match the C standard, and we will have something to make time and go directly to the point . For example, a â64-bit (8-byte) numbers in an integer format, scaled by 10,000 to give a fixed-point number with 15 digits to the left of the decimal point and 4 digits to the rightâ. So (int)39.48*100 will never return 3947 anymore, and brutal and lemmings coders like me will make better accountancy software. Thanks :) ------------------------------------------------------------------------ [2013-08-20 12:08:41] [email protected] You mean like this in Python: >>> int(39.48*100) 3947 >>> "%s" % (39.48 * 100) '3948.0' This is not PHP-specific in any way. ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at https://bugs.php.net/bug.php?id=65485 -- Edit this bug report at https://bugs.php.net/bug.php?id=65485&edit=1
