0

This is one of those questions where each little part seems to do what you want it to, but they won't work together.

Big picture: I'm running an experiment where each new visitor to the web page is automatically assigned to one of six conditions (we'll call them "A" through "F"). All I need is a way to keep track of how many people have visited so far, and use that information to calculate which group to assign them to. For instance, the 1st visitor would be in condition "A", the 6th in condition "F", and then the 7th back to condition "A" again, and so on. In other words, just a simple mod function.

In my real code, I keep track of visitor numbers and group assignments with a combination of text files and session variables. I've abstracted away from that here (please don't shoot me for using globals), but the same problem crops up in both cases: after stepping through the array nicely one time, I start getting erratic output that I don't understand. More puzzling still is that when I look at each step on its own, everything lines up. On the 8th time through, the weirdness starts. Let me walk you through it.

The first line below ("The output of SESSION['GroupAssignment'] is 2") correctly indicates that we want to pull from the [2]nd index of the array below it. A quick glance at that array tells you that -again, correctly- the [2]nd entry is "C". The final array, with only one entry, is the result of code that basically equates to $Array[2][0]. In any reasonable universe, that would return "C". But as you can see, it returns "B".

The output of SESSION['GroupAssginment'] is 2

Array
(
    [0] => Array
        (
            [0] => A
        )

    [1] => Array
        (
            [0] => B
        )

    [2] => Array
        (
            [0] => C
        )

    [3] => Array
        (
            [0] => D
        )

    [4] => Array
        (
            [0] => E
        )

    [5] => Array
        (
            [0] => F
        )

)
Array
(
    [0] => B
)
The text file for subject 8 will be B.

This kind of thing continues to happen repeatedly (reliably on the same numbers), but I can't figure out any discernible source or pattern. I hope you can! Code below:

<?
$Group = array(//structured like this 'cause my real experiment reads these from text files in a way that results in this structure.
            array("A"),
            array("B"),
            array("C"),
            array("D"),
            array("E"),
            array("F")
            );

$NumberOfGroups = count($Group);

for ($i=0; $i<48; $i++){ //current iteration ~ subject number
    CalculateMod($i, $NumberOfGroups);//given the current iteration, figure out which entry (0-5) you want to use.
    global $GroupAssignment_Outer;
    AssignGroup($i,$Group,$GroupAssignment_Outer);//go grab the right file from the inner array using the appropriate outer index.
}

function CalculateMod($value, $precision){//this part works perfectly. 

    $remainder = ($value/$precision - round($value/$precision));
    if ($remainder < 0){
        $remainder = $remainder+1;
    }
    global $GroupAssignment_Outer;
    $GroupAssignment_Outer = $remainder*$precision;
}

function AssignGroup($subjectnumber, $group, $outerindex){//the error must be somewhere in here... but where!?
    $GroupAssignment_Inner = $group[$outerindex][0];
    echo "The text file for subject " . $subjectnumber .  " will be " . $GroupAssignment_Inner . "<br>"; 
}

?>

In case it helps, here's the output of the above code:

The text file for subject 0 will be A
The text file for subject 1 will be B
The text file for subject 2 will be C
The text file for subject 3 will be D
The text file for subject 4 will be E
The text file for subject 5 will be F
The text file for subject 6 will be A
The text file for subject 7 will be B
The text file for subject 8 will be B
The text file for subject 9 will be D
The text file for subject 10 will be E
The text file for subject 11 will be F
The text file for subject 12 will be A
The text file for subject 13 will be A
The text file for subject 14 will be C
The text file for subject 15 will be D
The text file for subject 16 will be D
The text file for subject 17 will be F
The text file for subject 18 will be A
The text file for subject 19 will be A
The text file for subject 20 will be C
The text file for subject 21 will be D
The text file for subject 22 will be D
The text file for subject 23 will be F
The text file for subject 24 will be A
The text file for subject 25 will be B
The text file for subject 26 will be B
The text file for subject 27 will be D
The text file for subject 28 will be E
The text file for subject 29 will be E
The text file for subject 30 will be A
The text file for subject 31 will be B
The text file for subject 32 will be B
The text file for subject 33 will be D
The text file for subject 34 will be E
The text file for subject 35 will be E
The text file for subject 36 will be A
The text file for subject 37 will be B
The text file for subject 38 will be B
The text file for subject 39 will be D
The text file for subject 40 will be E
The text file for subject 41 will be E
The text file for subject 42 will be A
The text file for subject 43 will be B
The text file for subject 44 will be B
The text file for subject 45 will be D
The text file for subject 46 will be E
The text file for subject 47 will be E

1 Answer 1

2

I doubt that...

//this part works perfectly

There's a mod operator % for it.

for ($i=0; $i<48; $i++){
    AssignGroup($i,$Group,$i % $NumberOfGroups);
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks very much; that solved the issue. As someone who's still learning (obviously), I'd really like to understand exactly why the solution I came up with had different results. The reason I thought that it ought to work was they when you just look at the output of my original CalculateMod() function, it spits out the sequence of 0-5 over and over again, exactly as it ought to. I'd be very appreciative if you (or anyone else) could explain what was actually going on under the hood that led to the strange indexing behavior above. But still, thanks for giving me the proverbial fish!
It's basically rounding problem that comes with $remainder*$precision part. It gives you results extremely close to integer (2.9999...) and displays 3 but array index takes it's int value (2). Try with round($remainder*$precision) - should work fine.
When it comes to "fishing": Instead using globals this way (wrong even if you tolerate them!) you should just use return round($remainder*$precision); and assign variable to returned value from function call $x = CalculateMod(...) or even inject it directly into another function call AssignGroup($i,$Group,CalculateMod(...));
Excellent- I really appreciate you taking the time to explain!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.