ลบเลขศูนย์ที่ไม่มีประโยชน์ออกจากทศนิยมใน PHP


163

ฉันพยายามหาวิธีที่รวดเร็วในการลบออกzero decimalsจากค่าตัวเลขเช่นนี้:

echo cleanNumber('125.00');
// 125

echo cleanNumber('966.70');
// 966.7

echo cleanNumber(844.011);
// 844.011

มีวิธีเพิ่มประสิทธิภาพให้ทำเช่นนั้นหรือไม่?


4
เนื่องจากค่าของคุณเป็นสายอักขระทำไมไม่ใช้ rtrim () - php.net/manual/en/function.rtrim.php - ด้วย '0. ' เป็นอาร์กิวเมนต์ที่สอง
Mark Baker

ขออภัยฉันยังไม่ชัดเจนพวกเขาไม่ได้เป็นสตริงเสมอฉันแก้ไขคำถาม
vitto

9
@ Mark Baker: นั่นเป็นวิธีที่ไม่ดีเพราะหมายเลข 120 จะถูกตัดเป็น 12
machineaddict

@machineaddict - ถ้าเป็นเช่นนั้นก็ต่อเมื่อค่าสตริงไม่มีจุดทศนิยม ... ทุกอย่างที่อ้างโดย OP มีจุดทศนิยม
Mark Baker

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)แต่ฉันคิดว่ามันง่ายกว่า


45
ฉันคิดว่านี่เป็นเคล็ดลับสกปรก ฉันจะไม่ชอบมันเพราะรหัสไม่ได้บอกเกี่ยวกับพฤติกรรมของเขาที่ชอบfloatval()ทำ
ESCOBAR

4
พฤติกรรมfloatvalของ@ESCOBAR กำลังคืนค่าทศนิยม ฉันจะเถียงใช้เป็น formatter ทศนิยมไม่ชัดเจนหรือสะอาดทั้ง
lafor

2
นี่เป็นสิ่งที่ไม่ชัดเจน ทีมของเราเพิ่งพบสิ่งนี้ในรหัสของเราและมันมีนักพัฒนา 3 คนสับสนอยู่พักหนึ่ง ฉันคิดว่าคำตอบของมาร์คเป็นทางเลือกที่ดีกว่า มันยาวกว่า แต่เจตนาชัดเจน
jfbalanc

2
@jfbalanc//COMMENT
Webinan

1
@ESCOBAR ไม่ใช่วิธีที่แนะนำอย่างเป็นทางการสำหรับ typecasting ... ค้นหา "type juggling" บน php.net
Gergely Lukacsy

101

คุณสามารถใช้floatvalฟังก์ชั่นนี้ได้

echo floatval('125.00');
// 125

echo floatval('966.70');
// 966.7

echo floatval('844.011');
// 844.011

2
มันล้มเหลวเมื่อตัวคั่นหลักพันเป็นจุดและเครื่องหมายทศนิยมคือเครื่องหมายจุลภาค
Munna Khan

20

นี่คือสิ่งที่ฉันใช้:

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

NB นี้ถือว่า.เป็นตัวแยกทศนิยม มันมีข้อดีที่จะทำงานกับจำนวนมาก (หรือเล็ก) โดยพลการเนื่องจากไม่มีการส่งแบบลอย มันจะไม่เปลี่ยนตัวเลขให้เป็นสัญลักษณ์ทางวิทยาศาสตร์ (เช่น 1.0E-17)


นี่ไม่ใช่ทางออกที่ปลอดภัยจะเกิดอะไรขึ้นถ้าราคาไม่ใช่ทศนิยมตัวอย่างเช่นถ้านักพัฒนาทวีคูณราคาด้วยจำนวนเต็มเรามีจำนวนเต็ม
amin

@alex ฟังก์ชั่นนี้ทำงานกับจำนวนเต็มลอยและสตริง
mpen

1
โซลูชั่นที่สมบูรณ์แบบในฐานะผู้ช่วยสำหรับ bcmath
Kart Av1k

17

เพียงเพิ่ม+ตัวแปรสตริงของคุณจะทำให้ typecast ไปที่(ลอย)และลบศูนย์:

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

ขอบคุณฉันรักคำตอบนี้ สิ่งนี้มีประโยชน์มากสำหรับฉัน
Sumit Kumar Gupta

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;

ไม่มีอะไรที่ไม่สามารถแก้ไขได้ด้วย regex ง่าย ๆ )

http://xkcd.com/208/


1
แถบปิดที่สำคัญอาทิใน0 "100"ยังไม่สามารถถอด0s ออก"100.010"ได้
mpen

2
ทุกคนยืนกลับ! $x = preg_replace("/(\.0*$)|((?<=\.\d*)0+$)/",'',$x);
Emanuel S.


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

คุณกำลังตอบคำถามตั้งแต่ปี 2013
VTodorov

3
ไม่ใช่ปัญหาในการตอบคำถามเก่าถ้ามันสามารถช่วยผู้อ่านที่แท้จริง
Reign.85

1

แปลกเมื่อฉันได้รับตัวเลขจากฐานข้อมูลที่มีประเภท "ลอย" และถ้าหมายเลขของฉันคืออดีต 10,000 เมื่อฉันลอยค่ามันจะกลายเป็น 1

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

ฉันทดสอบวิธีแก้ปัญหาทั้งหมดข้างต้นแล้ว แต่ไม่ได้ผล



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



0

นั่นเป็นทางออกเล็ก ๆ ของฉัน ... สามารถรวมไว้ในชั้นเรียนและตั้งค่า vars

ส่วนตัว $ dsepparator = '.'; // decimals ส่วนตัว $ 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

0

นี่คือทางออกของฉัน ฉันต้องการเพิ่มความสามารถในการเพิ่มตัวคั่นหลักพัน

    $precision = 5;    
    $number = round($number, $precision);
    $decimals = strlen(substr(strrchr($number, '.'), 1));
    return number_format($number, $precision, '.', ',');

0

นี่คือฟังก์ชั่นหนึ่งบรรทัดที่เรียบง่ายโดยใช้ rtrim บันทึกตัวคั่นและจุดทศนิยม:

function myFormat($num,$dec)
 {
 return rtrim(rtrim(number_format($num,$dec),'0'),'.');
 }

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, ',', '.');
}

0

ง่ายและแม่นยำ!

function cleanNumber($num){
    $explode = explode('.', $num);
    $count   = strlen(rtrim($explode[1],'0'));
    return bcmul("$num",'1', $count);
}

0

ทางออกที่ดีที่สุด: วิธีเดียวที่ปลอดภัยคือใช้ regex:

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

มันจะทำงานได้ในทุกกรณี



-1
$value = preg_replace('~\.0+$~','',$value);

1
มันจะปรับปรุงคุณภาพของคำตอบของคุณหากคุณได้ให้คำอธิบายว่าโค้ดของคุณทำอะไรและจะแก้ปัญหาคำถามเดิมอย่างไร
Nigel Ren

@Nikhil Gyan ฉันเห็นด้วยกับคำตอบนี้ไม่ดี รู้สึกฟรี อย่างไรก็ตามอย่างน้อยฉันก็ไม่คิดว่ามันแย่พอสำหรับธงคุณภาพต่ำมาก
Sam Hartman

-2

รหัสนี้จะลบศูนย์หลังจากจุดและจะกลับทศนิยมเพียงสองหลัก

$ จำนวน = 1200.0000;
str_replace ('. 00', '', number_format ($ number, 2, '.', ''));

เอาต์พุตจะเป็น: 1200

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.