Удалите ненужные нули из десятичных дробей в PHP

164

Я пытаюсь найти быстрый способ удалить zero decimalsиз числовых значений, как это:

echo cleanNumber('125.00');
// 125

echo cleanNumber('966.70');
// 966.7

echo cleanNumber(844.011);
// 844.011

Существует ли какой-то оптимизированный способ сделать это?

Vitto
источник
4
Поскольку ваши значения на самом деле являются строками, почему бы просто не использовать rtrim () - php.net/manual/en/function.rtrim.php - с «0». в качестве второго аргумента
Марк Бейкер
Извините, я не совсем ясно, они не всегда строки, я исправляю вопрос.
vitto
9
@Mark Baker: это плохой подход, так как число 120 будет сокращено до 12
автоматическое решение
@machineaddict - было бы, если и только если строковые значения не имели десятичной точки ..... все цитируемые OP имеют десятичную точку.
Марк Бейкер,
2
Затем вы должны добавить жирный текст в ответ, что он работает только при наличии десятичных дробей.
Machineaddict

Ответы:

354

$num + 0 делает трюк.

echo 125.00 + 0; // 125
echo '125.00' + 0; // 125
echo 966.70 + 0; // 966.7

Внутренне это равносильно приведению к плавающему (float)$numили, floatval($num)но я нахожу это проще.

lafor
источник
45
Я думаю, что это подвох. я бы не предпочел, потому что код не говорит о его поведении, как будто он floatval()это делает.
ЭСКОБАР
4
Поведение @ESCOBAR floatval- всплеск . Я бы сказал, что использование его в качестве средства форматирования десятичных чисел не очень очевидно или чисто.
Lafor
2
Это очень неясно. Наша команда только что столкнулась с этим в нашем коде, и в течение некоторого времени у нее было 3 озадаченных разработчика. Я думаю, что ответ Марка - лучшая альтернатива. Это дольше, но его цель ясна.
jfbalanc
2
@jfbalanc//COMMENT
Webinan
1
@ESCOBAR Не совсем, это официально предложенный метод для приведения типов ... ищите «жонглирование типов» на php.net
Gergely Lukacsy
101

Вы могли бы просто использовать floatvalфункцию

echo floatval('125.00');
// 125

echo floatval('966.70');
// 966.7

echo floatval('844.011');
// 844.011
DiverseAndRemote.com
источник
2
сбой происходит, когда разделитель тысяч представляет собой точку, а десятичный знак - запятую.
Мунна Хан
20

Это то, что я использую:

function TrimTrailingZeroes($nbr) {
    return strpos($nbr,'.')!==false ? rtrim(rtrim($nbr,'0'),'.') : $nbr;
}

NB. Предполагается, .что это десятичный разделитель. Преимущество этого метода в том, что он будет работать с произвольно большими (или маленькими) числами, так как здесь нет приведения с плавающей точкой. Это также не превратит числа в научные обозначения (например, 1.0E-17).

mpen
источник
это не безопасное решение, что если цена не является десятичной? Например, если разработчик умножит цену на целое число, то получится целое число
amin
@alex Эта функция работает с целыми числами, числами с плавающей запятой и строками.
mpen
1
Идеальное решение в качестве помощника для bcmath
Kart Av1k
17

Простое добавление +в строковую переменную приведет к приведению типа (float) и удалит нули:

var_dump(+'125.00');     // double(125)
var_dump(+'966.70');     // double(966.7)
var_dump(+'844.011');    // double(844.011)
var_dump(+'844.011asdf');// double(844.011)
Александр Янчарук
источник
13

Для всех, кто заходит на этот сайт и сталкивается с такой же проблемой с запятыми, измените:

$num = number_format($value, 1, ',', '');

чтобы:

$num = str_replace(',0', '', number_format($value, 1, ',', '')); // e.g. 100,0 becomes 100


Если нужно удалить два нуля , измените на:

$num = str_replace(',00', '', number_format($value, 2, ',', '')); // e.g. 100,00 becomes 100

Подробнее здесь: номер PHP: десятичная точка видна только при необходимости

Кай Ноак
источник
10

Если вы хотите удалить нулевые цифры непосредственно перед отображением на странице или шаблоне.

Вы можете использовать функцию sprintf ()

sprintf('%g','125.00');
//125

‌‌sprintf('%g','966.70');
//966.7

‌‌‌‌sprintf('%g',844.011);
//844.011
Хемерсон Варела
источник
Спасибо, мне понравился этот ответ. Это очень полезно для меня.
Сумит Кумар Гупта
9

Вы должны разыгрывать свои числа как числа с плавающей точкой, что сделает это за вас.

$string = "42.422005000000000000000000000000";
echo (float)$string;

Результатом этого будет то, что вы ищете.

42.422005

Саджан Парих
источник
1
Кастинг с плавающей точкой также может повредить ваш номер. например (float)'0.1234567890124567890123456789'становится 0.12345678901246.
mpen
8
$x = '100.10'; 
$x = preg_replace("/\.?0*$/",'',$x); 
echo $x;

Нет ничего, что нельзя исправить с помощью простого регулярного выражения;)

http://xkcd.com/208/

Dakkaron
источник
1
Удаляет значительный 0с, например, в "100". Также не в состоянии раздеться 0сек от "100.010".
mpen
2
Все отступают! $x = preg_replace("/(\.0*$)|((?<=\.\d*)0+$)/",'',$x);
Эмануэль С.
5

Типа к float.

$int = 4.324000;
$int = (float) $int;
Джозеф А.
источник
2

Из-за этого вопрос старый. Во-первых, я сожалею об этом.

Вопрос касается числа xxx.xx, но в случае, если это x, xxx.xxxxx или десятичный разделитель разностей, такой как xxxx, xxxx, может быть сложнее найти и удалить нулевые цифры из десятичного значения.

/**
 * Remove zero digits from decimal value.
 * 
 * @param string|int|float $number The number can be any format, any where use in the world such as 123, 1,234.56, 1234.56789, 12.345,67, -98,765.43
 * @param string The decimal separator. You have to set this parameter to exactly what it is. For example: in Europe it is mostly use "," instead of ".".
 * @return string Return removed zero digits from decimal value.
 */
function removeZeroDigitsFromDecimal($number, $decimal_sep = '.')
{
    $explode_num = explode($decimal_sep, $number);
    if (is_array($explode_num) && isset($explode_num[count($explode_num)-1]) && intval($explode_num[count($explode_num)-1]) === 0) {
        unset($explode_num[count($explode_num)-1]);
        $number = implode($decimal_sep, $explode_num);
    }
    unset($explode_num);
    return (string) $number;
}

А вот и код для теста.

$numbers = [
    1234,// 1234
    -1234,// -1234
    '12,345.67890',// 12,345.67890
    '-12,345,678.901234',// -12,345,678.901234
    '12345.000000',// 12345
    '-12345.000000',// -12345
    '12,345.000000',// 12,345
    '-12,345.000000000',// -12,345
];
foreach ($numbers as $number) {
    var_dump(removeZeroDigitsFromDecimal($number));
}


echo '<hr>'."\n\n\n";


$numbers = [
    1234,// 12324
    -1234,// -1234
    '12.345,67890',// 12.345,67890
    '-12.345.678,901234',// -12.345.678,901234
    '12345,000000',// 12345
    '-12345,000000',// -12345
    '12.345,000000',// 12.345
    '-12.345,000000000',// -12.345
    '-12.345,000000,000',// -12.345,000000 STRANGE!! but also work.
];
foreach ($numbers as $number) {
    var_dump(removeZeroDigitsFromDecimal($number, ','));
}
ви
источник
2

Будьте осторожны с добавлением +0.

echo number_format(1500.00, 2,".",",")+0;
//1

Результат этого 1.

echo floatval('1,000.00');
// 1

echo floatval('1000.00');
//1000
OnionStand
источник
Вы отвечаете на вопрос 2013 года.
VTodorov
3
Это не проблема, чтобы ответить на старый вопрос, если это может помочь реальным читателям
Правление. 85.12.12
1

Странно, когда я получаю номер из базы данных с типом «float» и если мой номер - ex. 10000 когда я его плаваю, становится 1.

$number = $ad['price_month']; // 1000 from the database with a float type
echo floatval($number);
Result : 1

Я проверил все решения выше, но не сработал.

лио
источник
1
$str = 15.00;
$str2 = 14.70;
echo rtrim(rtrim(strval($str), "0"), "."); //15
echo rtrim(rtrim(strval($str2), "0"), "."); //14.7
RatajS
источник
0

Сложно, но работает:

$num = '125.0100';
$index = $num[strlen($num)-1];
$i = strlen($num)-1;
while($index == '0') {
   if ($num[$i] == '0') {
     $num[$i] = '';
     $i--;
   }

   $index = $num[$i];
}

//remove dot if no numbers exist after dot
$explode = explode('.', $num);
if (isset($explode[1]) && intval($explode[1]) <= 0) {
   $num = intval($explode[0]);
}

echo $num; //125.01

Приведенные выше решения являются оптимальным способом, но если вы хотите иметь свое собственное, вы можете использовать это. То, что делает этот алгоритм, он запускает в конце строки и проверяет , равен ли его 0 , если он установлен, то устанавливает пустую строку, а затем переходит к следующему символу сзади, пока последний символ не будет > 0

GGIO
источник
0

Ты можешь использовать:

print (floatval)(number_format( $Value), 2 ) );    
МУНЕРПАША ГАДАД
источник
0

Вот мое небольшое решение ... Может включать в класс и установить переменные

private $ dsepparator = '.'; // десятичные числа private $ tsepparator = ','; // тысяча

Это может быть установлено конструктором и изменено на lang пользователей.

class foo
{
    private $dsepparator;
    private $tsepparator;

    function __construct(){
        $langDatas = ['en' => ['dsepparator' => '.', 'tsepparator' => ','], 'de' => ['dsepparator' => ',', 'tsepparator' => '.']];
        $usersLang = 'de'; // set iso code of lang from user
        $this->dsepparator = $langDatas[$usersLang]['dsepparator'];
        $this->tsepparator = $langDatas[$usersLang]['tsepparator'];
    }

    public function numberOmat($amount, $decimals = 2, $hideByZero = false)
    {
        return ( $hideByZero === true AND ($amount-floor($amount)) <= 0 ) ? number_format($amount, 0, $this->dsepparator, $this->tsepparator) : number_format($amount, $decimals, $this->dsepparator, $this->tsepparator);
    }
    /*
     * $bar = new foo();
     * $bar->numberOmat('5.1234', 2, true); // returns: 5,12
     * $bar->numberOmat('5', 2); // returns: 5,00
     * $bar->numberOmat('5.00', 2, true); // returns: 5
     */

}
Paykoman
источник
Итак, я создал образец класса с небольшими образцами. Лучше? =)
Paykoman
0

Это моё решение. Я хочу сохранить возможность добавлять разделитель тысяч

    $precision = 5;    
    $number = round($number, $precision);
    $decimals = strlen(substr(strrchr($number, '.'), 1));
    return number_format($number, $precision, '.', ',');
despotbg
источник
0

Это простая однострочная функция, использующая rtrim, разделитель сохранения и десятичную точку:

function myFormat($num,$dec)
 {
 return rtrim(rtrim(number_format($num,$dec),'0'),'.');
 }
APH
источник
0

Я нашел это решение является лучшим:

public function priceFormat(float $price): string
{
    //https://stackoverflow.com/a/14531760/5884988
    $price = $price + 0;
    $split = explode('.', $price);
    return number_format($price, isset($split[1]) ? strlen($split[1]) : 2, ',', '.');
}
Rawburner
источник
0

Просто и точно!

function cleanNumber($num){
    $explode = explode('.', $num);
    $count   = strlen(rtrim($explode[1],'0'));
    return bcmul("$num",'1', $count);
}
Дж. Доу
источник
0

Окончательное решение: единственный безопасный способ - использовать регулярные выражения:

echo preg_replace("/\.?0+$/", "", 3.0); // 3
echo preg_replace("/\d+\.?\d*(\.?0+)/", "", 3.0); // 3

это будет работать в любом случае

Йоханес А.И.
источник
0

Следующее гораздо проще

if(floor($num) == $num) {
    echo number_format($num);
} else {
    echo $num;
}
Немрод Мондез
источник
-1
$value = preg_replace('~\.0+$~','',$value);
Нихил Гьян
источник
1
Это улучшит качество вашего ответа, если вы предоставите объяснение того, что делает ваш код и как он решит исходный вопрос.
Найджел Рен,
@Nikhil Gyan Я согласен, что этот ответ не велик. Не стесняйтесь записываться. Тем не менее, я, по крайней мере, не думаю, что это достаточно плохо для очень низкого качества флага
Сэм Хартман
-2

Этот код удалит ноль после точки и вернет только две десятичные цифры.

$ номер = 1200.0000;
str_replace ('. 00', '', number_format ($ number, 2, '.', ''));

Выход будет: 1200

Ашиш Патхак
источник