ส่งไปยัง int vs floor


120

มีความแตกต่างระหว่างสิ่งเหล่านี้หรือไม่:

float foo1 = (int)(bar / 3.0);
float foo2 = floor(bar / 3.0);

ตามที่ฉันเข้าใจทั้งสองกรณีมีผลเหมือนกัน มีความแตกต่างในโค้ดที่คอมไพล์หรือไม่?


1
ดีขึ้นเล็กน้อยด้วยfloorแต่ระวังว่านี้เป็นไม่ได้สำหรับdouble floatC99 ยังมีfloorfสำหรับfloat.
Jens Gustedt

2
ดังนั้นพวกเขาจึงได้ผลลัพธ์เช่นเดียวกันตราบเท่าที่บาร์เป็นบวก
Zac

1
(หมายเหตุ: โปรด#include<cmath>ใช้C ++ ใน C ++ std::floor)
user202729

ประเภทคือbarอะไร?
chux - คืนสถานะ Monica

@chux ไม่เป็นไรหารด้วย 3.0 จะทำให้เป็นสองเท่าอยู่ดี
kaalus

คำตอบ:


194

การแคสต์เป็น int จะตัดทอนเป็นศูนย์ floor()จะตัดทอนไปทางลบไม่มีที่สิ้นสุด สิ่งนี้จะให้ค่าที่แตกต่างกันหากbarเป็นลบ


15
ฉันคิดว่าคุณโดนตะปูที่หัวนี่ ความแตกต่างอีกประการหนึ่งหากfloor()เป็นเจตนาคือถ้าค่าของbarใหญ่เกินไปที่จะใส่ในintไฟล์.
Fred Larson

คุณมีแหล่งที่มาสำหรับคำสั่งนั้นหรือไม่?
HelloGoodbye

1
แม้ว่าผลลัพธ์จะเป็นบวกก็ไม่รับประกัน ดูนี้และนี้
user202729

27

ดังที่ได้กล่าวไว้ก่อนหน้านี้สำหรับจำนวนบวกจะเหมือนกัน แต่ต่างกันสำหรับจำนวนลบ กฎคือ int จะปัดเศษไปทาง 0 ในขณะที่พื้นจะปัดเศษเข้าหาอินฟินิตี้เชิงลบ

floor(4.5) = (int)4.5 = 4
floor(-4.5) = -5 
(int)(-4.5) = -4

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

ฉันมีรหัสที่ต้องการการดำเนินการขั้นพื้นฐานของช่วงค่าที่ จำกัด รวมถึงตัวเลขเชิงลบ และต้องมีประสิทธิภาพมากดังนั้นเราจึงใช้ฟังก์ชันต่อไปนี้สำหรับมัน:

int int_floor(double x) 
{ 
    return (int)(x+100000) - 100000; 
}

แน่นอนว่าสิ่งนี้จะล้มเหลวสำหรับค่า x ที่มีขนาดใหญ่มาก (คุณจะพบปัญหาล้น) และสำหรับค่าลบที่ต่ำกว่า -100000 เป็นต้น แต่ฉันได้โอเวอร์คล็อกให้เร็วกว่าพื้นอย่างน้อย 3 เท่าซึ่งสำคัญมาก สำหรับแอปพลิเคชันของเรา ใช้เกลือเม็ดทดสอบกับระบบของคุณ ฯลฯ แต่ก็คุ้มค่าที่จะพิจารณา IMHO


"ฉันโอเวอร์คล็อกให้เร็วกว่าพื้นอย่างน้อย 3 เท่า" -> OP ใช้floatไม่ใช่double- อาจdoubleเป็นแอปพลิเคชันของคุณ ถ้าอยู่ใน C ให้ใช้floorf()กับfloats
chux - คืนสถานะ Monica

@chux ฉันคิดว่าเหตุผลเดียวที่มีความแตกต่างคือการแคสต์ช่วยให้สามารถเพิ่มประสิทธิภาพเวลาคอมไพล์ได้ ดังนั้นการแปลงอาจถูกลบออกอย่างสมบูรณ์ในระหว่างการดำเนินการ
ClydeTheGhost

9

ดังนั้น 101 อย่าเปลี่ยนคำถามของคุณหลังจากที่มีคนตอบคำถามของคุณแล้วให้เขียนคำถามใหม่แทน

ทำไมคุณถึงคิดว่ามันจะได้ผลลัพธ์แบบเดียวกัน?

float foo = (int)(bar / 3.0) //will create an integer then assign it to a float

float foo = fabs(bar / 3.0 ) //will do the absolute value of a float division

bar = 1.0

foo1 = 0;
foo2 = 0.33333...

1
คุณหมายถึงfabsอะไร? floorคำถามคือเกี่ยวกับ ชั้นของ0.33333... คือ0.
Aaron Franke

2
@AaronFranke คำถามเดิมได้รับการแก้ไข ดูเหมือนว่าจะเกิดขึ้นได้มากมายใน 8 ปี ;-) สังเกตว่าคำตอบอื่น ๆ มีหลักฐานเดียวกัน
AndersK

4

แก้ไข: เพราะคำถามที่อาจจะได้รับการแก้ไขเนื่องจากสับสนระหว่างและfabs()floor()

กำหนดบรรทัดตัวอย่างคำถามเดิม:

1.  float foo = (int)(bar / 3.0);

2.  float foo = fabs(bar / 3.0);

ความแตกต่างคือถ้าบาร์เป็นลบผลลัพธ์จะเป็นลบกับตัวแรก แต่บวกกับอันที่สอง รายการแรกจะถูกตัดทอนเป็นจำนวนเต็มและวินาทีจะส่งกลับค่าทศนิยมเต็มรูปแบบรวมทั้งเศษส่วน


3

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


2

มีความแตกต่างหลักสองประการ:

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

  2. ดูเหมือนจะไม่มีใคร (ยัง) ชี้ให้เห็นความแตกต่างอื่น - ถ้าอาร์กิวเมนต์ของคุณมากกว่าหรือเท่ากับMAX_INT+1(หรือน้อยกว่า-MAX_INT-1) การแคสต์ไปยัง an intจะส่งผลให้บิตด้านบนสุดถูกทิ้ง (C อาจ) หรือพฤติกรรมที่ไม่ได้กำหนด ( C ++ และอาจเป็น C) เช่นถ้าคุณintเป็น 32 บิตคุณจะมีเพียงบิตเครื่องหมายบวกข้อมูล 31 บิต ดังนั้นการใช้สิ่งนี้กับdoubleขนาดที่ใหญ่จะให้ผลลัพธ์ที่ไม่ได้ตั้งใจ


2.a. เงื่อนไขที่แน่นอนสำหรับการแปลงเป็นintโอเวอร์คืออาร์กิวเมนต์มีค่ามากกว่าหรือเท่ากับINT_MAX+1 ในทางสมมาตรเงื่อนไขสำหรับ underflow คืออาร์กิวเมนต์ต่ำกว่าหรือเท่ากับINT_MIN-1
Pascal Cuoq

1
2.b. การล้นในการแปลงจากทศนิยมเป็นจำนวนเต็มเป็นพฤติกรรมที่ไม่ได้กำหนดใน C ++ มันไม่ได้“ ส่งผลให้บิตอันดับสูงสุดถูกทิ้ง” ดู (แม้ว่าจะเขียนสำหรับ C): blog.frama-c.com/index.php?post/2013/10/09/…
Pascal Cuoq

0

(int) xเป็นคำขอที่จะเก็บส่วนจำนวนเต็มของx(ไม่มีการปัดเศษที่นี่)

fabs(x)= | x | เพื่อให้มัน>= 0;

เช่น(int) -3.5ผลตอบแทน-3; fabs(-3.5)ผลตอบแทน3.5;

โดยทั่วไป fabs (x) >= xสำหรับ x ทั้งหมด

x >= (int) x ถ้า x >= 0

x < (int) x ถ้า x < 0


x = -3 fabs (-3) = 3 (int) -3 = -3; ฉันคิดว่าความไม่เท่าเทียมกันสุดท้ายมีอยู่ คุณช่วยอธิบายเพิ่มเติมได้ไหมว่าทำไมจึงผิด
Paul Hoang

ขอโทษนะฉันหมายถึง -3.5 ตามที่คุณยกมา -3> -3.5
Dennis Zickefoose

3
คำสั่งสุดท้ายควรยังคงเป็น "x <= int (x) ถ้า x <0" และไม่ใช่ "x <(int) x if x <0": จำนวนเต็มลบยังคงเหมือนเดิม
Tomasz Gandor
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.