ฉันจะแปลงเลขทศนิยมเป็นจำนวนเต็มใน JavaScript ได้อย่างไร


1110

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


83
หากคุณไม่ทราบตัวเลขทั้งหมดในจาวาสคริปต์จะเป็นแบบลอยตัว จากสเปค:
บาง

6
4.3.20 ประเภทหมายเลข: ประเภทหมายเลขคือชุดของค่าที่แทนตัวเลข ใน ECMAScript ชุดของค่าแสดงถึงค่า doubleprecision รูปแบบ 64 บิตค่า IEEE 754 รวมถึงค่าพิเศษ "Not-a-Number" (NaN) ค่าอินฟินิตี้บวกและอินฟินิตี้ลบ
บาง

9
ใช่ Javascript ไม่มีประเภท "จำนวนเต็ม" ที่แตกต่างกัน แต่ก็ยังไม่ใช่เรื่องแปลกที่จะต้องทำการแปลงนี้ ตัวอย่างเช่นในแอปพลิเคชันของฉันผู้ใช้พิมพ์ตัวเลข (อาจรวมถึงเซนต์) ฉันต้องตัดทอนเซนต์และแสดงด้วยเครื่องหมายจุลภาค ขั้นตอนที่ 1 คือการแปลงเป็น int
mcherm

1
ยังมีประโยชน์: การเปรียบเทียบความเร็วของวิธีการทั้งหมดjsperf.com/math-floor-vs-math-round-vs-parseint/33
c ..

1
@karl: ถ้าฉันยอมรับการป้อนข้อมูลลงในเขตข้อมูลฉันอาจควบคุมอักขระที่ฉันยอมรับได้ แต่ฉันสามารถทำการประมวลผลทุกชนิดใน Javascript ได้ไม่ใช่แค่ยอมรับการป้อนข้อมูลของผู้ใช้ ถึงอย่างนั้นฉันก็อาจต้องการมันเพื่อสนับสนุนการวาง
mcherm

คำตอบ:


1609
var intvalue = Math.floor( floatvalue );
var intvalue = Math.ceil( floatvalue ); 
var intvalue = Math.round( floatvalue );

// `Math.trunc` was added in ECMAScript 6
var intvalue = Math.trunc( floatvalue );

การอ้างอิงวัตถุทางคณิตศาสตร์


ตัวอย่าง

บวก
// value=x        //  x=5          5<x<5.5      5.5<=x<6  

Math.floor(value) //  5            5            5
Math.ceil(value)  //  5            6            6
Math.round(value) //  5            5            6
Math.trunc(value) //  5            5            5
parseInt(value)   //  5            5            5
~~value           //  5            5            5
value | 0         //  5            5            5
value >> 0        //  5            5            5
value >>> 0       //  5            5            5
value - value % 1 //  5            5            5
เชิงลบ
// value=x        // x=-5         -5>x>=-5.5   -5.5>x>-6

Math.floor(value) // -5           -6           -6
Math.ceil(value)  // -5           -5           -5
Math.round(value) // -5           -5           -6
Math.trunc(value) // -5           -5           -5
parseInt(value)   // -5           -5           -5
value | 0         // -5           -5           -5
~~value           // -5           -5           -5
value >> 0        // -5           -5           -5
value >>> 0       // 4294967291   4294967291   4294967291
value - value % 1 // -5           -5           -5
ค่าบวก - จำนวนที่มากกว่า
// x = Number.MAX_SAFE_INTEGER/10 // =900719925474099.1

// value=x            x=900719925474099    x=900719925474099.4  x=900719925474099.5

Math.floor(value) //  900719925474099      900719925474099      900719925474099
Math.ceil(value)  //  900719925474099      900719925474100      900719925474100
Math.round(value) //  900719925474099      900719925474099      900719925474100
Math.trunc(value) //  900719925474099      900719925474099      900719925474099
parseInt(value)   //  900719925474099      900719925474099      900719925474099
value | 0         //  858993459            858993459            858993459
~~value           //  858993459            858993459            858993459
value >> 0        //  858993459            858993459            858993459
value >>> 0       //  858993459            858993459            858993459
value - value % 1 //  900719925474099      900719925474099      900719925474099
ลบ - ตัวเลขที่ใหญ่ขึ้น
// x = Number.MAX_SAFE_INTEGER/10 * -1 // -900719925474099.1

// value = x      // x=-900719925474099   x=-900719925474099.5 x=-900719925474099.6

Math.floor(value) // -900719925474099     -900719925474100     -900719925474100
Math.ceil(value)  // -900719925474099     -900719925474099     -900719925474099
Math.round(value) // -900719925474099     -900719925474099     -900719925474100
Math.trunc(value) // -900719925474099     -900719925474099     -900719925474099
parseInt(value)   // -900719925474099     -900719925474099     -900719925474099
value | 0         // -858993459           -858993459           -858993459
~~value           // -858993459           -858993459           -858993459
value >> 0        // -858993459           -858993459           -858993459
value >>> 0       //  3435973837           3435973837           3435973837
value - value % 1 // -900719925474099     -900719925474099     -900719925474099

82
var intValue = ~~floatValue;ตามที่ระบุไว้ในคำตอบอื่นตัดลบปลอดภัยสามารถทำได้โดยใช้ หากสัญกรณ์คลุมเครือเกินไปสำหรับรสนิยมของคุณเพียงซ่อนไว้ในฟังก์ชั่น: function toInt(value) { return ~~value; }. (สิ่งนี้จะแปลงสตริงเป็นจำนวนเต็มถ้าคุณต้องการทำเช่นนั้น)
Keen

4
จะอัปโหลดถ้าคำตอบนี้มีตัวอย่างอินพุต / เอาต์พุต
J. Random Coder

7
เกี่ยวกับความคิดเห็น ~~ จำกัด ค่าให้เป็นจำนวนเต็ม 32 บิตในขณะที่ Math.floor / ceil / round สามารถจัดการได้ถึง 53 บิต (Number.MAX_SAFE_INTEGER 9007199254740991) สิ่งนี้ถูกกล่าวถึงในคำตอบด้านล่าง แต่มีค่าซ้ำสำหรับผู้ที่อ่านความคิดเห็นเหล่านี้
John

2
อ่านจากด้านล่างในหลายสถานที่: Math.trunc(val);แสดงความคิดเห็นเพราะนี่เป็นคำตอบที่ยอมรับ
Old Badman Gray

ไม่ทำงานด้วยความแม่นยำแน่นอนสำหรับค่าเช่น2.3 - 2.3 % 1
Lapys

301

ตัวดำเนินการระดับบิตหรือ

bitwise หรือโอเปอเรเตอร์สามารถใช้เพื่อตัดทอนตัวเลขจุดลอยตัวและใช้ได้กับผลบวกเช่นเดียวกับเนกาทีฟ:

function float2int (value) {
    return value | 0;
}

ผล

float2int(3.1) == 3
float2int(-3.1) == -3
float2int(3.9) == 3
float2int(-3.9) == -3

การเปรียบเทียบประสิทธิภาพ?

ฉันได้สร้างการทดสอบ JSPerfที่เปรียบเทียบประสิทธิภาพระหว่าง:

  • Math.floor(val)
  • val | 0 ค่าบิตหรือ
  • ~~val ไม่ bitwise
  • parseInt(val)

ใช้งานได้กับจำนวนบวกเท่านั้น ในกรณีนี้คุณปลอดภัยที่จะใช้การทำงานระดับบิตรวมทั้งMath.floorฟังก์ชั่น

แต่ถ้าคุณต้องการให้โค้ดทำงานกับผลบวกและเนกาทีฟการดำเนินการระดับบิตจะเร็วที่สุด (หรือเป็นรหัสที่ต้องการ) การทดสอบ JSPerf อื่น ๆ นี้เปรียบเทียบสิ่งเดียวกันกับที่เห็นได้ชัดว่าเนื่องจากการตรวจสอบเครื่องหมายเพิ่มเติมทางคณิตศาสตร์ตอนนี้ช้าที่สุดในสี่รายการ

บันทึก

ตามที่ระบุไว้ในความคิดเห็นผู้ประกอบการ BITWISE ทำงานกับจำนวนเต็ม 32 บิตที่ลงนามดังนั้นจำนวนมากจะถูกแปลงตัวอย่างเช่น:

1234567890  | 0 => 1234567890
12345678901 | 0 => -539222987

@FabioPoloni: ใช่ง่ายมากและดูเหมือนว่าผู้ประกอบการระดับบิตที่เร็วที่สุด โดยเฉพาะอย่างยิ่งตัวดำเนินการ OR มักจะทำงานเร็วที่สุดเสมอโดยการทำงานของ NOT และคณิตศาสตร์แม้ว่าการดำเนินการทางคณิตศาสตร์นั้นจะช้าที่สุดเมื่อคุณต้องรองรับจำนวนลบเช่นกัน
Robert Koritnik

9
@thourourtheye: การดำเนินการระดับบิตทั้งหมดยกเว้นการเลื่อนขวาที่ไม่ได้ลงชื่อและทำงานกับจำนวนเต็ม 32 บิตที่ลงชื่อแล้ว ดังนั้นการใช้การดำเนินการ bitwise กับค่าทศนิยมจะแปลงให้เป็นจำนวนเต็มลอกตัวเลขหลังจุดทศนิยม
Robert Koritnik

3
หากคุณต้องการเพียงตัวเลขบวกMath.floor()ก็จะเร็วขึ้น (อย่างน้อยตามการทดสอบ JSPerfครั้งแรกของฉันใน Google Chrome รุ่น 30.0.1599.101) มีประสิทธิภาพมากขึ้น (เพราะไม่ได้ขึ้นอยู่กับการแสดงตัวเลขเป็นบิต ซึ่งอาจมีการเปลี่ยนแปลงและอาจทำลายวิธีแก้ปัญหาระดับบิตนี้) และที่สำคัญที่สุดชัดเจนมากขึ้น
ma11hew28

8
โปรดทราบว่าตัวดำเนินการ bitwise ทำงานบนหมายเลข 32 บิต พวกมันจะไม่ทำงานกับตัวเลขที่ใหญ่เกินไปที่จะใส่ลงใน 32 บิต
Kat

2
~~ดีกว่าเพราะมันเป็นโอเปอเรเตอร์ unary 4.2|0+4เท่ากับ4แต่~~4.2+4เท่ากับ8
Janus Troelsen

94

หมายเหตุ: คุณไม่สามารถใช้Math.floor()แทนการตัดทอนได้เพราะMath.floor(-3.1) = -4ไม่ใช่-3!!

การแทนที่ที่ถูกต้องสำหรับการตัดจะเป็น:

function truncate(value)
{
    if (value < 0) {
        return Math.ceil(value);
    }

    return Math.floor(value);
}

1
ขึ้นอยู่กับพฤติกรรมที่ต้องการสำหรับจำนวนลบ การใช้งานบางอย่างต้องการตัวเลขเชิงลบเพื่อแมปกับค่าลบมากขึ้น (-3.5 -> -4) และบางอย่างต้องการให้แมปกับจำนวนเต็มขนาดเล็ก (-3.5 -> -3) อดีตมักเรียกว่า "ชั้น" คำว่า "truncate" มักใช้เพื่ออธิบายพฤติกรรมทั้งสองอย่าง ในกรณีของฉันฉันแค่ป้อนตัวเลขลบ แต่ความคิดเห็นนี้เป็นคำเตือนที่มีประโยชน์สำหรับผู้ที่สนใจเกี่ยวกับพฤติกรรมจำนวนลบ
mcherm

28
@mcherm: ดูเหมือนว่าพวกเขาจะไม่เข้าใจคำว่า "truncate" อย่างถูกต้อง การตัดทอนทำตามชื่อของมัน: มันตัดทอนตัวเลข มันไม่เคย (ในความหมายทั่วไป) เทียบเท่ากับพื้นหรือเพดาน en.wikipedia.org/wiki/Truncation
Thanatos

5
Math.trunc(value)ถูกเพิ่มใน ECMAScript 6
4esn0k

2
floorรอบต่อ - อนันต์, truncateปัดเศษเป็นศูนย์ ( ceilปัดไปทาง + อินฟินิตี้)
Peter Cordes

46

สามารถใช้โอเปอเรเตอร์bitwiseสองเท่าไม่ได้เพื่อตัดทอน การดำเนินงานอื่น ๆ ที่คุณกล่าวถึงเป็นใช้ได้ผ่านMath.floor, และMath.ceilMath.round

> ~~2.5
2
> ~~(-1.4)
-1

รายละเอียดเพิ่มเติมได้รับความอนุเคราะห์จาก James Padolsey


1
นี่อาจจะเป็นสิ่งที่ไม่ดีที่ต้องทำสำหรับรหัสการผลิต (เพราะมันไม่ชัดเจน) แต่มันก็เป็นสิ่งที่ฉันจำเป็นสำหรับรหัสการเล่นกอล์ฟของฉัน<canvas>เครื่องมือการแสดงผลตัวอักษรใน JS ขอบคุณ!
Kragen Javier Sitaker

10
สิ่งนี้สามารถทำได้ด้วย n | 0.
Jay Douglass

17
โปรดทราบว่าวิธีใดวิธีหนึ่ง (~~ n หรือ n | 0) จะใช้กับตัวเลขที่มีค่าไม่เกิน 2 ^ 31-1 หรือ 2147483647 เท่านั้น 2147483648 หรือสูงกว่าจะให้ผลลัพธ์ที่ไม่ถูกต้อง ตัวอย่างเช่น 2147483647 | 0 ผลตอบแทน -2147483648 และ 4294967295 | 0 ผลตอบแทน -1 ซึ่งเกือบจะไม่ใช่สิ่งที่คุณต้องการอย่างแน่นอน
Ed Bayiates

40

สำหรับการตัด:

var intvalue = Math.floor(value);

สำหรับรอบ:

var intvalue = Math.round(value);

6
Math.floor ไม่ตัดทอนค่าลบ ดูคำตอบข้างต้น คำตอบที่ดีเป็นอย่างอื่น
oligofren

หากคุณสนใจในประสิทธิภาพฉันได้ใส่เคสทดสอบไว้ที่นี่: jsperf.com/dsafdgdfsaf/2 (var | 0 ชนะที่นี่)
Cybolic

25

คุณสามารถใช้วิธีparseIntโดยไม่มีการปัดเศษ ระมัดระวังการป้อนข้อมูลผู้ใช้เนื่องจากตัวเลือกนำหน้า 0x (hex) และ 0 (octal)

var intValue = parseInt(floatValue, 10);

1
สิ่งนี้มีประโยชน์จริง ๆ เมื่อคุณต้องการส่วนจำนวนเต็มของทศนิยมโดยไม่ต้องปัดเศษขึ้นหรือลงซึ่งเป็นสิ่งที่. round, .ceil และ. floor ทำทั้งหมด
Judah Gabriel Himango

1
... แม้เมื่อตัดทอนสิ่งนี้ดูเหมือนจะเป็นวิธีที่ช้าที่สุด jsperf.com/float-to-int-conversion-comparison
Robert Koritnik

2
ส่งค่าที่ 2 ไปยัง parseInt เสมอเพื่อระบุฐานที่คุณคาดหวัง ดังนั้น parseInt (floatValue, 10) เสมอรับฐาน 10
Tim Tisdall

3
แม้ว่านี่จะเก่า แต่คำถามนี้ดูเหมือนจะเป็นคำถามที่ถามบ่อยดังนั้นฉันจะใส่คำเตือนไว้ที่นี่ หากค่าจะแสดงโดยใช้เครื่องหมาย "e" เนื่องจากขนาดของมันก็จะส่งผลในตัวเลขหนึ่งหลักไม่ใช่สิ่งที่คาดหวัง ตัวอย่างเช่นparseInt(1000000000000000000000, 10);ผลลัพธ์ใน 1 ไม่ใช่ 1 000 000 000 000 000 000 000 อย่างไรก็ตามคำถามไม่ต้องการ " แปลงเป็นสตริงและการแยกวิเคราะห์ " อย่างชัดเจนแม้ว่าจะค่อนข้างน้อย ... ;)
แควนตัส 94 หนัก

4
@ Qantas94Heavy สาเหตุของการทำงานนี้เกิดขึ้นเนื่องจากparseInt()คาดว่าสตริงจะไม่ใช่ตัวเลขเป็นพารามิเตอร์แรก เมื่อคุณผ่านจำนวนเต็มนี้จะถูกแปลงเป็น1e21แล้วparseIntจะแยกวิเคราะห์สตริงซึ่งผลในการ1e21 1
Olaf Dietsche

18

การเลื่อนบิต 0 ซึ่งเทียบเท่ากับการหารด้วย 1

// >> or >>>
2.0 >> 0; // 2
2.0 >>> 0; // 2

4
บันทึกขนาดเล็ก: >> 0ดูเหมือนว่าจะทำงานเฉพาะสำหรับจำนวนเต็ม < 2 ^ 31-1และ>>> 0สำหรับจำนวนเต็ม < 2 ^ 32-1 สิ่งนี้จะคืนค่า 0 สำหรับค่าที่มากกว่า
Romuald Brunet

@RomualdBrunet ใช่ JavaScript กำหนดการดำเนินการระดับบิตทั้งหมดอย่างชัดเจนว่าทำงานบนตัวเลข 32 บิต ที่อยู่ในรายละเอียด
Alexis Wilke

การทำงานเช่นเดียวกับ Javascript จะทำงานในระดับบิตกับจำนวนเต็ม 32 บิต (ลงนาม) ตามที่ระบุไว้ในคำตอบข้างต้น ดังนั้นการทำงานแบบบิตใด ๆ ที่ดูเหมือนจะไม่ทำอะไรเลย (เช่น shift สำหรับ 0, หรือด้วย 0, และ 1, double not) ยังต้องการล่าม Javascript เพื่อแปลงค่าเป็น 32 บิต int
FrankKrumnow

9

ในกรณีของคุณเมื่อคุณต้องการสตริงในท้ายที่สุด (เพื่อแทรกเครื่องหมายจุลภาค) คุณยังสามารถใช้Number.toFixed()ฟังก์ชันได้ แต่สิ่งนี้จะทำการปัดเศษ


7

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

intval = floatval - floatval%1;

วิธีนี้ยังทำงานกับตัวเลขที่มีมูลค่าสูงซึ่งทั้ง '| 0' หรือ '~~' หรือ '>> 0' ทำงานไม่ถูกต้อง:

> n=4294967295;
> n|0
-1
> ~~n
-1
> n>>0
-1
> n-n%1
4294967295

หากคุณอ้างถึงคำตอบอื่นโปรดเพิ่มการอ้างอิงหรือร่างความคิดในไม่ช้า
bertl

5

วิธีตัดทอน :

// Math.trunc() is part of the ES6 spec
Math.trunc( 1.5 );  // returns 1
Math.trunc( -1.5 ); // returns -1
// Math.floor( -1.5 ) would return -2, which is probably not what you wanted

ถึงรอบ :

Math.round( 1.5 );  // 2
Math.round( 1.49 ); // 1
Math.round( -1.6 ); // -2
Math.round( -1.3 ); // -1

5

อีกวิธีหนึ่งที่เป็นไปได้ - ใช้การดำเนินการ XOR:

console.log(12.3 ^ 0); // 12
console.log("12.3" ^ 0); // 12
console.log(1.2 + 1.3 ^ 0); // 2
console.log(1.2 + 1.3 * 2 ^ 0); // 3
console.log(-1.2 ^ 0); // -1
console.log(-1.2 + 1 ^ 0); // 0
console.log(-1.2 - 1.3 ^ 0); // -2

ลำดับความสำคัญของการดำเนินการระดับบิตที่น้อยกว่าลำดับความสำคัญของการดำเนินการทางคณิตศาสตร์มันมีประโยชน์ ลองที่https://jsfiddle.net/au51uj3r/


2

หากมองไปที่Mathวัตถุพื้นเมืองใน JavaScript คุณจะได้รับฟังก์ชั่นมากมายในการทำงานกับตัวเลขและค่า ฯลฯ

โดยทั่วไปสิ่งที่คุณต้องการทำนั้นค่อนข้างง่ายและเป็นภาษาจาวาสคริปต์ ...

ลองนึกภาพคุณมีหมายเลขด้านล่าง:

const myValue = 56.4534931;

และตอนนี้ถ้าคุณต้องการปัดเศษมันเป็นตัวเลขที่ใกล้ที่สุดเพียงแค่ทำ:

const rounded = Math.floor(myValue);

และคุณจะได้รับ:

56

หากคุณต้องการปัดเศษขึ้นเป็นตัวเลขที่ใกล้ที่สุดให้ทำดังนี้

const roundedUp = Math.ceil(myValue);

และคุณจะได้รับ:

57

นอกจากนี้Math.roundเพียงแค่ปัดมันเป็นจำนวนที่สูงหรือต่ำกว่านั้นขึ้นอยู่กับว่าใครอยู่ใกล้กับจำนวน flot

นอกจากนี้คุณสามารถใช้~~หลังตัวเลขลอยที่จะแปลงลอยเป็นจำนวนเต็ม

คุณสามารถใช้มันเหมือน~~myValue...


โปรดระมัดระวังด้วย~~เพราะถ้าตัวเลขมีขนาดใหญ่กว่าขีด จำกัด int 32 มันจะเปลี่ยนค่าเป็นค่าขีด จำกัด int 32
Machado


0

ฉันแค่อยากจะชี้ให้เห็นว่าคุณต้องการปัดเศษรายได้โดยไม่ตัดทอน การถูกเพนนีมีโอกาสน้อยกว่ามากเนื่องจากการปัดเศษ 4.999452 * 100 จะให้ 5 คำตอบที่เป็นตัวแทนของคุณมากกว่า

อย่าลืมเกี่ยวกับการปัดเศษของนายธนาคารซึ่งเป็นวิธีที่จะตอบโต้อคติเชิงบวกเล็กน้อยที่การปัดเศษให้ตรง - ใบสมัครทางการเงินของคุณอาจต้องการ

การปัดเศษแบบเกาส์ / นายธนาคารใน JavaScript


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