2

In PHP, I know we shouldn't do math on floats without things like bcmath, but is the mere act of casting a string to float destructive?

Will expressions like (float)'5.111' == '5.111', always be true? Or will the cast itself change that to something like 5.1110000000000199837 as the number is converted?

The main reason is, just as I use (int) to escape integer values going into a database, I would like to use (float) in the same way, without having to rely on quotes and my escape function.

Eric Leschinski
  • 135,913
  • 89
  • 401
  • 325
Andrew
  • 5,015
  • 6
  • 39
  • 48
  • it's better to rely on quotes. Especially because you don't have to use floats at all but **decimal** instead. There is nothing really bad in quotes and treating ALL data the same way (as strings) – Your Common Sense Jan 10 '11 at 18:26
  • Yes, Casting your string to a float will change its value. The question to be asking google is: "Why does `0.1` plus `0.2` not equal `0.3` in floating point arithmetic in all programming languages?" The answer is because the computer has no way to represent exactly 0.2 in software using base-2 binary numbers. Here is a great video explaining the problem: https://www.youtube.com/watch?v=PZRI1IfStY0 – Eric Leschinski Mar 18 '15 at 14:26

3 Answers3

1

You shouldn't use (int) to escape integer values. Use a parametrized query and set the type of your input to 'int'. A much better way!

for an example in mysql/php see: http://us.php.net/manual/en/mysqli.prepare.php

Nanne
  • 63,347
  • 16
  • 116
  • 159
  • 1
    There is nothing wrong with casting to an `int`. While I do agree that parametrized queries are better in general, it's not because it's any safer. The only way it's safer is that it forces you to escape. But if you escape yourself, it's just as safe as with using parametrized queries. There's absolutely nothing wrong with forcing a type prior to appending to a query. Sure, there are other ways of doing it that may have advantages, but it's not implicitly wrong as implied by your wording. – ircmaxell Jan 10 '11 at 17:25
  • If I could use parameters, I would, but I can't. Since the question wasn't specifically about that, I didn't feel the need to dissertate why I wasn't using mysqli/PDO. – Andrew Jan 10 '11 at 17:33
1

It depends on whether or not the fractional part can be represented exactly in binary (see Fractions in binary). For example, 0.5 has an exact binary representation but 0.1 does not. If the number does not have an exact representation, you are likely to see a different result when printing it again.

casablanca
  • 68,094
  • 7
  • 131
  • 148
1

NO, Casting to a float is almost always destructive.

In your example, 5.111 represented in binary is:

101.00011100011010100111111011111001110110110010001011010000111001...

A float would store 23 digits:

101.0001110001101010011 
(5.1109981536865234375)

A double would store 52 digits:

101.0001110001101010011111101111100111011011001000101
(5.1109999999999988773424774990417063236236572265625)

In this case, there wouldn't be a difference. However, in larger numbers, it can affect what you display.

For example:

1025.4995

double:

10000000001.011111111101111100111011011001000101101
(1025.499499999999898136593401432037353515625)

float:

10000000001.011111111101
(1025.499267578125)

You can see the precision starts to drop off dramatically after around 8 digits.

The double would round to 1025.4995 whereas the float would be 1025.4993

Eric Leschinski
  • 135,913
  • 89
  • 401
  • 325
Armstrongest
  • 14,744
  • 13
  • 64
  • 105
  • This really concerns me now, because `number_format` casts the input to float, as does `money_format`... – Andrew Jan 10 '11 at 19:36
  • I don't think I'd cast money to float... but it depends on what you're doing as to whether it matters in a practical sense. If you're dealing with numbers less than 10000.00 and you only need penny precision it probably wouldn't matter. Also, when you lose precision the casted number will ALWAYS be smaller, not larger. – Armstrongest Jan 11 '11 at 22:08