วิธีที่เร็วที่สุดในการแปลง String เป็น Number ใน JavaScript คืออะไร?


122

หมายเลขใดก็หมายเลข สตริงดูเหมือนตัวเลขมันคือตัวเลข อย่างอื่นมันไปที่ NaN

'a' => NaN
'1' => 1
1 => 1

สิ่งที่เร็วที่สุดขึ้นอยู่กับการเพิ่มประสิทธิภาพในการใช้งานที่กำหนดในช่วงเวลาที่กำหนด ไม่มีวิธีที่ "เร็วที่สุด" อย่างเป็นกลาง
I Hate Lazy

2
'1a'สตริงจะทำอย่างไร กับ' 1'หนึ่ง? กล่าวอีกนัยหนึ่งทำไมวิธีการทั่วไปส่วนใหญ่ในการทำเช่นนั้น ( Number(x)และparseInt(x, 10)) จึงไม่เพียงพอสำหรับคุณ?
raina77ow

การทดสอบ jsperf ก่อนหน้านี้: jsperf.com/converting-string-to-int/3
epascarello

นี่คือการเปรียบเทียบประสิทธิภาพที่ดีของวิธีการต่างๆ: jsben.ch/#/NnBKM
EscapeNetscape

คำตอบ:


192

มี 4 วิธีในการทำเท่าที่ฉันรู้

Number(x);
parseInt(x, 10);
parseFloat(x);
+x;

จากการทดสอบด่วนที่ฉันทำขึ้นนี้ขึ้นอยู่กับเบราว์เซอร์จริงๆ

http://jsperf.com/best-of-string-to-number-conversion/2

Implicit ทำเครื่องหมายว่าเร็วที่สุดใน 3 เบราว์เซอร์ แต่ทำให้อ่านรหัสยาก…ดังนั้นเลือกสิ่งที่คุณต้องการ!


7
Google Analytics ที่น่าสนใจ (ส่วนที่คุณวางในเว็บไซต์ของคุณ) ใช้1*สำหรับการแปลงวันที่เป็นตัวเลขซึ่งคล้ายกับ+ข้างต้น คือมากกว่า1*new Date() +new Date()อาจเป็นไปได้ว่ามันอ่านง่ายขึ้น?
Matthew Wilcoxson

1
ฉันคิดว่า1*เป็นที่ต้องการเพราะมีโอกาสเกิดข้อผิดพลาดน้อยกว่า ตัวแปรห้อยที่ไม่ต้องการก่อน+1ไม่ใช่ข้อผิดพลาดในการแยกวิเคราะห์ มันเป็นเคล็ดลับที่คล้ายกับการใช้if (MYCONSTANT == myvar)ในC.
Tomas

5
@beatak - การเพิ่มประสิทธิภาพในปัจจุบันดูเหมือนจะสนับสนุนวิธีการดั้งเดิมมากกว่าการแปลงโดยปริยาย ฉันเริ่มทำงานได้เร็วที่สุดสำหรับ Number () ใน Chrome 37.0.2062.124 บน Windows Server 2008 R2 / 7 และ ParseInt () ใน Firefox 30.0 โดยปริยายว่าช้าที่สุดสำหรับทั้งสองอย่าง นอกจากนี้คุณอาจพิจารณารวมการลอยตัวแบบสตริงในการทดสอบเพื่อเปรียบเทียบทั่วไป ฉันเดาว่าอาจเปลี่ยนลำดับในบางกรณีเนื่องจากการแปลง string to float โดยทั่วไปจะช้ากว่าการแปลงสตริงเป็น int วิธีการทดสอบในขณะนี้มันเริ่มต้นด้วยการแปลงสตริงเป็น int เมื่อใช้ Number ()
Nolo

1
Chrome 61.0.3163 Number () เร็วที่สุด
Dmitry Petukhov

70

มีอย่างน้อย 5 วิธีในการดำเนินการนี้:

หากคุณต้องการแปลงเป็นจำนวนเต็มเท่านั้นวิธีอื่นที่เร็ว (และสั้น) คือdouble-bitwise not (เช่นใช้อักขระทิลเดอสองตัว):

เช่น

~~x;

อ้างอิง: http://james.padolsey.com/cool-stuff/double-bitwise-not/

วิธีทั่วไป 5 วิธีที่ฉันรู้จนถึงตอนนี้ในการแปลงสตริงเป็นตัวเลขล้วนมีความแตกต่าง (มีตัวดำเนินการระดับบิตมากกว่าที่ใช้งานได้ แต่ทั้งหมดนี้ให้ผลลัพธ์เหมือนกัน~~) JSFiddle นี้แสดงผลลัพธ์ที่แตกต่างกันที่คุณคาดหวังในคอนโซลการแก้ปัญหา: http://jsfiddle.net/TrueBlueAussie/j7x0q0e3/22/

var values = ["123",
          undefined,
          "not a number",
          "123.45",
          "1234 error",
          "2147483648",
          "4999999999"
          ];

for (var i = 0; i < values.length; i++){
    var x = values[i];

    console.log(x);
    console.log(" Number(x) = " + Number(x));
    console.log(" parseInt(x, 10) = " + parseInt(x, 10));
    console.log(" parseFloat(x) = " + parseFloat(x));
    console.log(" +x = " + +x);
    console.log(" ~~x = " + ~~x);
}

คอนโซลดีบัก:

123
  Number(x) = 123
  parseInt(x, 10) = 123
  parseFloat(x) = 123
  +x = 123
  ~~x = 123
undefined
  Number(x) = NaN
  parseInt(x, 10) = NaN
  parseFloat(x) = NaN
  +x = NaN
  ~~x = 0
null
  Number(x) = 0
  parseInt(x, 10) = NaN
  parseFloat(x) = NaN
  +x = 0
  ~~x = 0
"not a number"
  Number(x) = NaN
  parseInt(x, 10) = NaN
  parseFloat(x) = NaN
  +x = NaN
  ~~x = 0
123.45
  Number(x) = 123.45
  parseInt(x, 10) = 123
  parseFloat(x) = 123.45
  +x = 123.45
  ~~x = 123
1234 error
  Number(x) = NaN
  parseInt(x, 10) = 1234
  parseFloat(x) = 1234
  +x = NaN
  ~~x = 0
2147483648
  Number(x) = 2147483648
  parseInt(x, 10) = 2147483648
  parseFloat(x) = 2147483648
  +x = 2147483648
  ~~x = -2147483648
4999999999
  Number(x) = 4999999999
  parseInt(x, 10) = 4999999999
  parseFloat(x) = 4999999999
  +x = 4999999999
  ~~x = 705032703

~~xผลรุ่นจำนวนใน "มากกว่า" กรณีที่คนอื่นมักจะส่งผลให้มีundefinedแต่จะล้มเหลวสำหรับการป้อนข้อมูลที่ไม่ถูกต้อง (เช่นมันจะกลับมา0ถ้าสตริงมีอักขระจำนวนไม่ใช่หลังจากที่ตัวเลขที่ถูกต้อง)

ล้น

โปรดทราบ: จำนวนเต็มล้นและ / หรือการตัดบิตอาจเกิดขึ้น~~ได้กับ Conversion อื่น ๆ แม้ว่าจะเป็นเรื่องผิดปกติที่จะป้อนค่าจำนวนมากเช่นนี้ แต่คุณต้องตระหนักถึงสิ่งนี้ ตัวอย่างที่อัปเดตเพื่อรวมค่าที่ใหญ่กว่ามาก

การทดสอบ Perf บางรายการระบุว่ามาตรฐานparseIntและparseFloatฟังก์ชันเป็นตัวเลือกที่เร็วที่สุดซึ่งคาดว่าเบราว์เซอร์จะได้รับการปรับให้เหมาะสม แต่ทั้งหมดขึ้นอยู่กับความต้องการของคุณเนื่องจากตัวเลือกทั้งหมดนั้นเร็วพอ : http://jsperf.com/best-of-string-to -number แปลง / 37

ทั้งหมดนี้ขึ้นอยู่กับวิธีกำหนดค่าการทดสอบความสมบูรณ์แบบเนื่องจากการแสดง parseInt / parseFloat จะช้ากว่ามาก

ทฤษฎีของฉันคือ:

  • โกหก
  • เส้นยี้
  • สถิติ
  • ผลลัพธ์ JSPerf :)

3
โปรดใช้ความระมัดระวังจริงๆสำหรับตัวเลขที่มีขนาดใหญ่กว่า 2147483647. เช่น ผลตอบแทน~~4294967296 0
Joseph Goh

@JosephGoh: เมื่อฉันมีโอกาสฉันจะขยายผลเพื่อรวมช่วง int ล้น โดยทั่วไปหากตัวเลขมีขนาดใหญ่คุณมีอินเทอร์เฟซพิเศษที่เกิดขึ้นดังนั้นจะต้องระวังการล้น Cheers
Gone Coding

@JosephGoh: ที่น่าสนใจใน Chrome คุณไม่ได้ 0 คุณจะได้ตัวเลขติดลบเกินค่าสูงสุดที่ลงนาม จากนั้นดูเหมือนว่าจะปล่อยบิตพิเศษเมื่อคุณเกินค่า int สูงสุดที่ไม่ได้ลงชื่อ เช่น "4999999999" => 705032703
Gone Coding


7

วิธีที่รวดเร็วในการแปลงสตริงเป็นจำนวนเต็มคือการใช้บิตหรือดังนี้:

x | 0

แม้ว่าจะขึ้นอยู่กับวิธีการนำไปใช้ แต่ในทางทฤษฎีควรจะค่อนข้างเร็ว (อย่างน้อยก็เร็วที่สุด+x) เนื่องจากจะส่งxไปยังตัวเลขก่อนแล้วจึงมีประสิทธิภาพมากหรือ


ใช่ แต่ฉันเชื่อว่าเทคนิคนี้ตัดทอนจำนวนเต็มขนาดใหญ่ซึ่งค่อนข้างแย่ เพื่อให้ทราบว่าฉันสามารถใช้แทน Math.floor () ได้ แต่มีปัญหาเดียวกัน
ฌอง

นี่คือjsperf ของตัวดำเนินการระดับบิตต่างๆร่วมกับวิธีการในคำตอบแรก ฉันสุ่มลำดับเนื่องจากพบว่าเบราว์เซอร์บางตัวจะเพิ่มประสิทธิภาพการทดสอบครั้งต่อไปโดยใช้รหัสที่คล้ายกันจากการทดสอบครั้งก่อน ฉันพบว่านัยเป็นวิธีการที่แย่ที่สุด
พลูโต

4

นี่คือวิธีง่ายๆในการทำ: var num = Number (str); ในตัวอย่างนี้strคือตัวแปรที่มีสตริง คุณสามารถทดสอบและดูวิธีการทำงานได้โดยเปิด: เครื่องมือสำหรับนักพัฒนา Google Chromeจากนั้นไปที่คอนโซลและวางโค้ดต่อไปนี้ อ่านความคิดเห็นเพื่อทำความเข้าใจวิธีการแปลงที่ดีขึ้น

// Here Im creating my variable as a string
var str = "258";


// here im printing the string variable: str
console.log ( str );


// here Im using typeof , this tells me that the variable str is the type: string
console.log ("The variable str is type: " + typeof str);


// here is where the conversion happens
// Number will take the string in the parentesis and transform it to a variable num as type: number
var num = Number(str);
console.log ("The variable num is type: " + typeof num);


3

นี่อาจจะไม่เร็วขนาดนั้น แต่มีประโยชน์เพิ่มเติมในการตรวจสอบให้แน่ใจว่าตัวเลขของคุณมีค่าอย่างน้อยค่าหนึ่ง (เช่น 0) หรือค่าสูงสุดที่แน่นอน:

Math.max(input, 0);

หากคุณต้องการตรวจสอบมูลค่าขั้นต่ำโดยปกติคุณจะต้องทำ

var number = Number(input);
if (number < 0) number = 0;

Math.max(..., 0) ช่วยให้คุณประหยัดจากการเขียนสองคำสั่ง


ทำไมไม่ใช้Math.abs(input)? นอกจากนี้ยังแปลงสตริงเป็นจำนวนบวกและบันทึกอักขระพิเศษบางตัว
Aaron Gillion

1
@AaronGillion: Math.max (-5, 0) จะคืนค่า 0; Math.abs (-5) จะส่งกลับ 5 ขึ้นอยู่กับกรณีการใช้งานซึ่งเหมาะสมกว่า
Dan Dascalescu

1
อ๊ะอ๊ะใช่กรณีการใช้งานของฉันแตกต่างกันในช่วงดึกที่ฉันเขียนความคิดเห็นนั้น
Aaron Gillion

หากinputไม่สามารถแปลงเป็นตัวเลขได้คุณจะได้รับNaN
Domas

0

คุณสามารถลองใช้UnitOfซึ่งเป็นไลบรารีการแปลงการวัดและประเภทข้อมูลที่เราเพิ่งเปิดตัวอย่างเป็นทางการ! UnitOf นั้นเร็วมากมีขนาดเล็กและมีประสิทธิภาพในการแปลงข้อมูลทุกประเภทโดยไม่เคยเกิดข้อผิดพลาดหรือเป็นโมฆะ / ไม่ได้กำหนด ค่าเริ่มต้นที่คุณกำหนดหรือค่าเริ่มต้นของ UnitOf จะถูกส่งกลับเมื่อการแปลงไม่สำเร็จ

//One liner examples
UnitOf.DataType("12.5").toFloat(); //12.5 of type Float is returned. 0 would be returned if conversion failed.
UnitOf.DataType("Not A Num").toInt(10); //10 of type Int is returned as the conversion failed.

//Or as a variable
var unit = UnitOf.DataType("12.5");
unit.toInt(5); //12.5 of type Float is returned. 5 would be returned if the conversion failed.
unit.toFloat(8); // 12 of type Int is returned. 8 would be returned if the conversion failed.

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