İnt ile zemine yayınlama


120

Bunlar arasında herhangi bir fark var mı:

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

Anladığım kadarıyla her iki durumda da aynı sonuç var. Derlenen kodda herhangi bir fark var mı?


1
ile biraz daha iyi floor, ama bunun için doubleolmadığına dikkat edin float. C99 ayrıca vardır floorfiçin float.
Jens Gustedt

2
Dolayısıyla, çubuk pozitif olduğu sürece aynı sonuca sahipler
Zac

1
(not: C ++ ile lütfen #include<cmath>ve kullanın std::floor)
user202729


@chux önemli değil, 3.0'a böl her
halükarda

Yanıtlar:


193

Bir int'e çevrim sıfıra doğru kısalacaktır. floor()negatif sonsuza doğru kırpılır. barNegatif olsaydı bu size farklı değerler verecektir .


15
Sanırım burada kafasına çivi çaktın. Diğer bir fark, eğer floor()niyet ise, değerinin barbir int.
Fred Larson

Bu ifade için herhangi bir kaynağınız var mı?
HelloGoodbye

1
Sonuç olumlu olsa bile garanti edilmez. Bunu ve buna bakın .
user202729

27

Daha önce söylendiği gibi, pozitif sayılar için aynıdırlar, ancak negatif sayılar için farklıdırlar. Kural, int sıfıra yuvarlarken, taban negatif sonsuza yuvarlanır.

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

Bununla birlikte, yürütme süresinde de bir fark var. Sistemimde, dökümün zeminden en az 3 kat daha hızlı olduğunu zamanladım.

Negatif sayılar da dahil olmak üzere sınırlı bir değer aralığının kat işlemine ihtiyaç duyan kodum var. Ve çok verimli olması gerekiyor, bu yüzden bunun için aşağıdaki işlevi kullanıyoruz:

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

Elbette bu, çok büyük x değerleri (bazı taşma sorunları yaşarsınız) ve -100000'in altındaki negatif değerler için başarısız olur. Ama bunu zeminden en az 3 kat daha hızlı olarak ayarladım, bu gerçekten kritikti uygulamamız için. Bir tuz tanesi ile alın, sisteminizde test edin, vb. Ancak IMHO'yu dikkate almaya değer.


"Bunu zeminden en az 3 kat daha hızlı olacak şekilde ayarladım" -> OP kullanıyor float, doublebelki doublede sizin uygulamanızdı. C ise, s floorf()ile kullandığınızdan emin olun float.
chux - Monica'yı eski durumuna getir

@chux Bence herhangi bir fark olmasının tek nedeni, dökümün derleme zamanı optimizasyonuna izin vermesidir. Dolayısıyla, bu dönüşüm aslında yürütme sırasında tamamen kaldırılmış olabilir.
ClydeTheGhost

9

SO 101, insanlar sorunuza cevap verdikten sonra sorunuzu değiştirmeyin, bunun yerine yeni bir soru yazın.

Neden aynı sonuca sahip olacaklarını düşünüyorsunuz?

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
Ne demek istiyorsun fabs? Soru hakkındaydı floor. 0.33333... zemini 0.
Aaron Franke

2
@AaronFranke orijinal soru değiştirildi. Görünüşe göre 8 yılda çok şey olabilir ;-) diğer cevapların da aynı önermeye sahip olduğunu fark et
AndersK

4

DÜZENLEME: Çünkü soru fabs()ve arasındaki karışıklık nedeniyle değiştirilmiş olabilir floor().

Orijinal soru örnek satırları göz önüne alındığında:

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

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

Aradaki fark, çubuk negatifse, sonucun ilkinde negatif, ikincisinde pozitif olmasıdır. Birincisi bir tam sayıya kısaltılır ve ikincisi, kesirli kısım dahil olmak üzere tam ondalık değeri döndürür.


3

Evet. fabsargümanının mutlak değerini döndürür ve int'e çevrim, bölümün kesilmesine (en yakın int'e kadar) neden olur, bu nedenle sonuçlar neredeyse her zaman farklı olacaktır.


2

İki temel fark vardır:

  1. Diğerlerinin de belirttiği gibi, bir tamsayıya çevrim sıfıra doğru kesilecek, oysa floor()her zaman negatif sonsuza doğru kesilecektir; bu, negatif bir operand için farklı bir davranıştır.

  2. Hiç kimse (henüz) başka bir farklılığa işaret etmemiş gibi görünüyor - eğer argümanınız büyük veya eşitse MAX_INT+1(veya daha azsa -MAX_INT-1), o zaman bir inten üstteki bitlerin düşmesine (muhtemelen C) veya tanımsız davranışa ( C ++ ve muhtemelen C). Örneğin, eğer sizin int32 bit ise, sadece bir işaret biti artı 31 bit veriye sahip olacaksınız. Yani bunu doublebüyük boyutlu bir a ile kullanmak istenmeyen sonuçlar üretecektir.


2.a. Taşmaya dönüştürme için kesin koşul int, bağımsız değişkenin INT_MAX+ 1'e eşit veya daha büyük olmasıdır . Simetrik olarak, alt taşmanın koşulu, bağımsız değişkenin INT_MIN-1'e eşit veya daha düşük olmasıdır .
Pascal Cuoq

1
2.b. Kayan noktadan tam sayıya dönüşümdeki taşma, C ++ 'da tanımsız bir davranıştır. "En üstteki bitlerin düşmesine neden olmaz". Bakınız (C için yazılmış olmasına rağmen): blog.frama-c.com/index.php?post/2013/10/09/…
Pascal Cuoq

0

(int) xtamsayı kısmını tutma isteğidir x(burada yuvarlama yoktur)

fabs(x)= | x | öyle ki >= 0;

Ör: (int) -3.5iadeler -3; fabs(-3.5)döner 3.5;

Genel olarak, fabs (x) >= xtüm x'ler için;

x >= (int) x Eğer x >= 0

x < (int) x Eğer x < 0


x = -3 fabs (-3) = 3 (int) -3 = -3; Sanırım son eşitsizlikler geçerli. Neden yanlış olduğu konusunda daha fazla ayrıntı verebilir misiniz?
Paul Hoang

Üzgünüm, verdiğin örnek -3,5 demek istedim. -3> -3.5
Dennis Zickefoose

3
Son ifade hala x <0 ise "x <= int (x) olmalı ve" x <(int) x eğer x <0 "olmamalıdır: negatif tamsayılar aynı kalır.
Tomasz Gandor
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.