-2

The following code generates two random decimal values, then subtracts them to get $c.

$a = mt_rand(5, 75);
$b = mt_rand(5, 75);
$adjuster = mt_rand(2, 20);

do {
    $decimal_selector = mt_rand(1, 6);
    if ($decimal_selector == 1) {
        $a = $a / 10;
        $b = $b / 10;
    }
    if ($decimal_selector == 2) {
        $a = $a / 10;
        $b = $b / 100;
    }
    if ($decimal_selector == 3) {
        $a = $a / 100;
        $b = $b / 10;
    }
    if ($decimal_selector == 4) {
        $a = $a / 100;
        $b = $b / 100;
    }
    if ($decimal_selector == 5) {
        $a = $a / 1000;
        $b = $b / 1000;
    }
    if ($decimal_selector == 6) {
        $a = $a / 1000;
        $b = $b / 100;
    }

    if($b < $a)
        $b = $b + ($a - $b) + $adjuster;

    $c = $b - $a;
} while((is_int($a) == true && is_int($b) == true) || is_int($c) == true);

The do-while loop is trying to ensure that $a and $b are both not integers, and also that $c is not an integer. But I keep getting times where $c actually is an integer.

If I use gettype it keeps saying $c is a "double". Why, when $c ends up being something like 7?

EDIT: I keep getting random infinite loops from this code below. Any ideas why?

        do{
            $a = mt_rand(5, 75);
            $b = mt_rand(5, 75);
            $adjuster = mt_rand(2, 20);

            $decimal_selector = mt_rand(1, 6);
            if ($decimal_selector == 1){
                $a = $a / 10;
                $b = $b / 10;
            }
            if ($decimal_selector == 2){
                $a = $a / 10;
                $b = $b / 100;
            }
            if ($decimal_selector == 3){
                $a = $a / 100;
                $b = $b / 10;
            }
            if ($decimal_selector == 4){
                $a = $a / 100;
                $b = $b / 100;
            }
            if ($decimal_selector == 5){
                $a = $a / 1000;
                $b = $b / 1000;
            }
            if ($decimal_selector == 6){
                $a = $a / 1000;
                $b = $b / 100;
            }

            if($b < $a){
                $b = $b + ($a - $b) + $adjuster;
            }

            $c = $b - $a;

            if(intval($c) == $c) {
                $c_is_int = 1;
            } else {
                $c_is_int = 0;
            }

echo intval($c) . '<br>';
echo $c_is_int . '<br>';
echo $c . '<br><br>';
        } while($c_is_int == 1);

enter image description here

gtilflm
  • 1,389
  • 1
  • 21
  • 51

2 Answers2

4

A double subtracting a double results in a double, even if that number is a whole number

$c = (int) ($b - $a);
skrilled
  • 5,350
  • 2
  • 26
  • 48
  • That's silly! Anyway, I don't want to ensure that $c is an integer, I want to see if it ends up that way. Won't your casting of `($b - $a)` as an integer make it be an integer? – gtilflm Dec 04 '13 at 00:20
  • 1
    if(($c % 2)==0) { /* this is a whole number */ } else { /* this is not a whole number */ } – skrilled Dec 04 '13 at 00:29
  • @jszobody: I tried implementing your code and I keep getting infinte loops. I've edited the question showing the code. Any ideas? – gtilflm Dec 04 '13 at 00:42
  • @gtilflm I answered your infinite loop question in a comment under my posted answer – jszobody Dec 04 '13 at 00:47
3

Do something like this to see if $c is a whole number (possibly stored as a double):

if(intval($c) == $c) {
    echo "I'm a whole number";
}

See here: http://3v4l.org/ubPK4

jszobody
  • 28,495
  • 6
  • 61
  • 72
  • 1
    @gtilflm Your infinite loop is happening because you set `$c_is_int` to 1, but you have no `} else { $c_is_int = 0; }` So once it's set to 1, it's always 1. It's working here: http://3v4l.org/XBuHD – jszobody Dec 04 '13 at 00:45
  • Thanks. I added that in, but... amazingly, this loop STILL isn't working. I'm still ending up with whole numbers for `$c`. I have no idea why. I echoed `intval($c)` and `$c` and it seems to be producing weird results. – gtilflm Dec 04 '13 at 00:53
  • I updated the original post with some debugging code at the bottom of the loop. – gtilflm Dec 04 '13 at 00:57
  • If you run that code over and over, you end up getting whole numbers for `$c`. I'm doing this on a WAMP Server... could that be an issue? – gtilflm Dec 04 '13 at 01:01
  • Do you NEVER expect whole numbers? I'm getting mix of whole and non-whole numbers. Isn't that right? – jszobody Dec 04 '13 at 01:02
  • No, I don't want $c to ever be a whole number. I'm ok with $a and $b individually being whole numbers, but not BOTH of them being whole numbers. – gtilflm Dec 04 '13 at 01:05
  • I just uploaded a screen snip of a weird result I got. – gtilflm Dec 04 '13 at 01:07
  • It's entirely possible for $a and $b to both be doubles, and yet $c is a whole number. I just got `a: 5.7 b: 24.7 c: 19` in one of my test runs. Sure looks legit to me, I still don't get why it's unexpected. – jszobody Dec 04 '13 at 01:08
  • That's the role of the do-while loop. It's to prevent $c from being a whole number. – gtilflm Dec 04 '13 at 01:10
  • `$c` can still be a whole number, it just breaks the next loop cycle. Or rather, the opposite (since you continue the loop when $c IS a whole number). See here: http://3v4l.org/N0FkP. The loop stops whenever the while condition is no longer true for $c. – jszobody Dec 04 '13 at 01:13
  • I think you misunderstand do/while loops. Anything can happen inside a loop cycle (including _any_ value for $c), it will just then stop and not proceed with the _next_ cycle. – jszobody Dec 04 '13 at 01:14
  • I just got this from your code: a: 4.4. b: 17.4. c: 13 (is NOT int!) – gtilflm Dec 04 '13 at 01:15
  • I think it's a floating point rounding error. I think $c is ending up at `12.9999999....` and then `intval()` rounds down, such that 13 and 12 are not the same. Rounding the number first before running through intval seems to work: http://3v4l.org/Abg80. But that's nasty. This might warrant a new question on PHP floating point handling. – jszobody Dec 04 '13 at 01:26
  • See here: http://stackoverflow.com/questions/3726721/php-math-precision. One of those answers also suggests using `round()` first before doing floating point arithmetic. – jszobody Dec 04 '13 at 01:27
  • I've reapplied your accepted answer, but the issue still remains. Your edited answer still doesn't ensure that `$c` doesn't end up as a whole number. – gtilflm Dec 04 '13 at 01:35
  • To be clear: your loop isn't about _preventing_ `$c` from ending up as a whole number, but rather detecting when it it (or isn't) a whole number. Let me know if you have a use case where the `round()` approach fails to accurately tell you if `c$` is a whole number or not, since that is what it is meant to do yeah? – jszobody Dec 04 '13 at 01:50
  • The loop should be preventing it. I've reposted about this issue here: http://stackoverflow.com/questions/20365368/loop-not-working-correctly-floats-and-integer-issue-php – gtilflm Dec 04 '13 at 01:54