lcg_value

Returns a pseudo-random float between 0 and 1 from a combined linear congruential generator.

Signature
lcg_value(): float
  • Added in PHP 4.0
  • Deprecated since PHP 8.4.0

Return value

floatA pseudo-random float in the open range (0, 1) — never exactly 0 and never exactly 1.

Changelog

  • PHP 8.4.0The function is deprecated. Every call emits an E_DEPRECATED notice; use Random\Randomizer::getFloat() instead.

The direct replacement is Random\Randomizer::getFloat(), available since PHP 8.3.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Reading legacy code that predates the Random extension and deciding what to replace it with
  • Migrating an old probability check such as if (lcg_value() < 0.1) to Randomizer::getFloat()
  • Adding non-critical jitter to a sampling rate in a script that still targets PHP 8.3

Frequently asked questions

Is lcg_value deprecated in PHP 8.5?

Yes — it was deprecated in PHP 8.4 and still emits an E_DEPRECATED notice on 8.5. It has not been removed yet, but you should migrate to Random\Randomizer::getFloat().

What should I use instead of lcg_value?

Use Random\Randomizer::getFloat($min, $max, Random\IntervalBoundary::ClosedOpen), available since PHP 8.3, for a correctly distributed float in an interval you control. For a simple percentage check, mt_rand(1, 100) is simpler and has no float rounding issues.

Can I use lcg_value for security tokens?

No. It is a pair of linear congruential generators whose state can be recovered from a handful of outputs, so its values are guessable. Use random_bytes() or random_int() for anything that must be unpredictable.

More examples

Migrating a probability check

This is the modern form of the classic if (lcg_value() < 0.25) log sampler. The printed rate lands close to 0.250 on every run, showing the replacement keeps the same behaviour without the deprecation notice.

Example · php
<?php
$randomizer = new Random\Randomizer();
$sampleRate = 0.25;

$hits = 0;
for ($i = 0; $i < 10000; $i++) {
    if ($randomizer->getFloat(0, 1, Random\IntervalBoundary::ClosedOpen) < $sampleRate) {
        $hits++;
    }
}

echo "sampled: $hits of 10000\n";
printf("rate: %.3f (target %.2f)\n", $hits / 10000, $sampleRate);

Why the open interval matters

Across 5000 draws the values crowd towards both ends but never touch them, and the last line prints false. Code written as if (lcg_value() == 0) or a loop waiting for an exact boundary will never fire.

Example · php
<?php
$sawZero = false;
$min = 1.0;
$max = 0.0;

for ($i = 0; $i < 5000; $i++) {
    $v = @lcg_value();
    if ($v === 0.0) { $sawZero = true; }
    $min = min($min, $v);
    $max = max($max, $v);
}

printf("lowest seen:  %.8f\n", $min);
printf("highest seen: %.8f\n", $max);
echo 'exact 0.0 ever returned: ', var_export($sawZero, true), "\n";

Discussion

  • Be the first to comment on this lesson.