Неожиданное поведение в PHP - тот же код дает правильные результаты в С# и Python - программирование

Неожиданное поведение в PHP - тот же код дает правильные результаты в С# и Python

Почему PHP возвращает INF (бесконечность) для следующего фрагмента кода:

<?php
$n = 1234;
$m = 0;

while ($n > 0)
{
    $m = ($m * 10) + ($n % 10);
    $n = $n / 10;
}

var_dump($m);
?>

Ожидаемый результат: 4321, но PHP вернул INF, тип float:

float INF

Я написал тот же код в Python и С# и получил ожидаемый результат - 4321

Python

n = 1234
m = 0

while (n > 0):
    m = (m * 10) + (n % 10)
    n = n / 10

print m

С#

static void Main(string[] args)
{
    int n = 1234;
    int m = 0;

    while (n > 0)
    {
        m = (m * 10) + (n % 10);
        n = n / 10;
    }

    Console.WriteLine(m);
    Console.ReadLine();
}
4b9b3361

Ответ 1

В php $n / 10 будет возвращено число с плавающей точкой, а не целое число.

Итак, $n > 0 всегда будет true.

Изменить while($n > 0)

до while($n > 1) или while((int)$n > 0), тогда вы получите правильный результат.

Ответ 2

PHP беспринципный и преобразует "на лету".

Это означает, что $n никогда не будет "0" или ниже, потому что $n будет "плавать", когда это необходимо.

Попробуйте проверить < 1, и вы должны быть в порядке.

Чтобы прояснить это, $n будет вести себя следующим образом:

$n = 1234 $ n = 123,4 $ n = 12,34 $ n = 1.234 $ n = 0.1234 $ n = 0.01234 и др.

Значение: $n всегда будет приближаться к 0, но никогда не достигнет его. Это делает $m бесконечным, так как сам цикл бесконечен.

Ответ 3

Что происходит:

$n = $n / 10;

Выполняет float-деление вместо целочисленного деления, поэтому $n никогда не достигает значения 0, оно просто приближается к значению 0, то есть 0.0... 1234.

Изменение приведенного выше кода:

$n = (int)($n / 10);

Устранит проблему.

Ответ 4

в правильном алгоритме используется floor()

<?php
$n = 1234;
$m = 0;

while ($n > 0)
{
    $m = $m * 10 + ($n % 10);
    $n = floor($n / 10);
}

var_dump($m);

Ответ 5

Это более вероятно из-за типичной арифметики с плавающей запятой.

Если вы используете математическую математику произвольной точности BCMath, она не имеет такого же эффекта.

$n = 1234;
$m = 0;

while ($n > 0)
{
    $m = bcmul($m, 10) + bcmod($n, 10);
    $n = bcdiv($n, 10);
}

var_dump($m);

http://codepad.viper-7.com/FYNCyN

См. также:

http://php.net/manual/en/language.types.float.php

Ответ 6

$n = intval($n / 10);

Это, похоже, решило проблему.