C'de verilen bir sayının çift mi yoksa tek mi olduğunu nasıl kontrol edebilirim?
C'de verilen bir sayının çift mi yoksa tek mi olduğunu nasıl kontrol edebilirim?
Yanıtlar:
2'ye bölerken kalanların olup olmadığını kontrol etmek için modulo (%) operatörünü kullanın:
if (x % 2) { /* x is odd */ }
Birkaç kişi cevabımı x & 1 kullanmanın "daha hızlı" veya "daha verimli" olduğunu belirterek eleştirdi. Bunun böyle olduğuna inanmıyorum.
Meraktan, iki önemsiz test vaka programı oluşturdum:
/* modulo.c */
#include <stdio.h>
int main(void)
{
int x;
for (x = 0; x < 10; x++)
if (x % 2)
printf("%d is odd\n", x);
return 0;
}
/* and.c */
#include <stdio.h>
int main(void)
{
int x;
for (x = 0; x < 10; x++)
if (x & 1)
printf("%d is odd\n", x);
return 0;
}
Daha sonra bunları makinelerimden birinde 5 farklı kez gcc 4.1.3 ile derledim:
Her derlemenin derleme çıktısını inceledim (gcc -S kullanarak) ve her durumda and.c ve modulo.c çıktılarının aynı olduğunu gördüm (her ikisi de andl $ 1,% eax komutunu kullandılar). Bunun "yeni" bir özellik olduğundan şüpheliyim ve eski sürümlere dayantığından şüpheleniyorum. Ayrıca herhangi bir modern (son 20 yılda yapılan) gizli olmayan derleyici, ticari veya açık kaynaklı, bu tür bir optimizasyondan yoksundur. Diğer derleyicileri test ederdim ama şu anda elimde hiç yok.
Başka herhangi bir derleyici ve / veya platform hedefini test etmek ister ve farklı bir sonuç alırsa, bilmek isterim.
Son olarak, modulo sürümü, uygulamanın imzalanmış tamsayıları temsil etmesine bakılmaksızın, tamsayı pozitif, negatif veya sıfır olsun, standart tarafından çalışacağı garanti edilir. Bitsel ve sürümü değildir. Evet, ikisinin tamamlayıcının biraz yaygın olduğunu fark ediyorum, bu yüzden bu gerçekten bir sorun değil.
Sizler waaaaaaaay çok verimlisiniz. Gerçekten istediğiniz şey:
public boolean isOdd(int num) {
int i = 0;
boolean odd = false;
while (i != num) {
odd = !odd;
i = i + 1;
}
return odd;
}
İçin tekrarlayın isEven
.
Tabii ki, bu negatif sayılar için işe yaramıyor. Ama parlaklıkla fedakarlık gelir ...
Bit aritmetiği kullanın:
if((x & 1) == 0)
printf("EVEN!\n");
else
printf("ODD!\n");
Bu, bölme veya modül kullanmaktan daha hızlıdır.
[Şaka modu = "açık"]
public enum Evenness
{
Unknown = 0,
Even = 1,
Odd = 2
}
public static Evenness AnalyzeEvenness(object o)
{
if (o == null)
return Evenness.Unknown;
string foo = o.ToString();
if (String.IsNullOrEmpty(foo))
return Evenness.Unknown;
char bar = foo[foo.Length - 1];
switch (bar)
{
case '0':
case '2':
case '4':
case '6':
case '8':
return Evenness.Even;
case '1':
case '3':
case '5':
case '7':
case '9':
return Evenness.Odd;
default:
return Evenness.Unknown;
}
}
[Şaka modu = "kapalı"]
DÜZENLEME: Numaralandırmaya kafa karıştırıcı değerler eklendi.
Ffpf'ye yanıt olarak - yıllar önce bir meslektaşımla tam olarak aynı tartışmayı yaptım ve cevap hayır , negatif sayılarla çalışmıyor.
C standardı, negatif sayıların 3 şekilde temsil edilebileceğini öngörür:
Böyle kontrol ediliyor:
isEven = (x & 1);
2'nin tamamlayıcısı ve işaret ve büyüklük gösterimi için çalışır, ancak 1'in tamamlayıcısı için çalışmaz.
Ancak, aşağıdakilerin tüm durumlar için işe yarayacağına inanıyorum:
isEven = (x & 1) ^ ((-1 & 1) | ((x < 0) ? 0 : 1)));
Metin kutusunun benim karakterimden sonra her şeyi yediğini gösteren ffpf sayesinde!
Güzel bir tane:
/*forward declaration, C compiles in one pass*/
bool isOdd(unsigned int n);
bool isEven(unsigned int n)
{
if (n == 0)
return true ; // I know 0 is even
else
return isOdd(n-1) ; // n is even if n-1 is odd
}
bool isOdd(unsigned int n)
{
if (n == 0)
return false ;
else
return isEven(n-1) ; // n is odd if n-1 is even
}
Bu yöntemin iki işlevi içeren kuyruk özyineleme kullandığını unutmayın. Derleyiciniz bir Scheme derleyicisi gibi kuyruk özyinelemeyi destekliyorsa verimli bir şekilde (bir süre / döngü türüne dönüşebilir) uygulanabilir. Bu durumda, yığın taşmamalıdır!
Bir sayı, ikiye bölündüğünde, geri kalan 0 ise bile. Bir sayı, 2'ye bölündüğünde, geri kalan 1 ise gariptir.
// Java
public static boolean isOdd(int num){
return num % 2 != 0;
}
/* C */
int isOdd(int num){
return num % 2;
}
Yöntemler harika!
i % 2 == 0
Ben sadece 2 ile bölmek söyleyebilirim ve 0 kalan varsa, hatta, aksi takdirde garip.
(%) Modülünü kullanmak bunu kolaylaştırır.
Örneğin. % 4 2 = 0 bu nedenle 4 çift bile% 5 2 = 1 bu nedenle 5 tek
Soruna bir çözüm daha
(çocuklar oy kullanabilirler)
bool isEven(unsigned int x)
{
unsigned int half1 = 0, half2 = 0;
while (x)
{
if (x) { half1++; x--; }
if (x) { half2++; x--; }
}
return half1 == half2;
}
Ben tamsayıların pariteler bir tablo (0 olsa bile 1) inşa ediyorum (böylece bir arama yapabilir: D), ama gcc bana bu boyutlarda diziler yapmak izin vermez:
typedef unsigned int uint;
char parity_uint [UINT_MAX];
char parity_sint_shifted [((uint) INT_MAX) + ((uint) abs (INT_MIN))];
char* parity_sint = parity_sint_shifted - INT_MIN;
void build_parity_tables () {
char parity = 0;
unsigned int ui;
for (ui = 1; ui <= UINT_MAX; ++ui) {
parity_uint [ui - 1] = parity;
parity = !parity;
}
parity = 0;
int si;
for (si = 1; si <= INT_MAX; ++si) {
parity_sint [si - 1] = parity;
parity = !parity;
}
parity = 1;
for (si = -1; si >= INT_MIN; --si) {
parity_sint [si] = parity;
parity = !parity;
}
}
char uparity (unsigned int n) {
if (n == 0) {
return 0;
}
return parity_uint [n - 1];
}
char sparity (int n) {
if (n == 0) {
return 0;
}
if (n < 0) {
++n;
}
return parity_sint [n - 1];
}
Öyleyse bunun yerine çift ve tekin matematiksel tanımına başvuralım.
N tamsayısı, n = 2k olacak şekilde bir k tamsayısı olsa bile olur.
N = 2k + 1 olacak şekilde k tamsayısı k varsa, n tamsayısı tuhaftır.
İşte bunun için kod:
char even (int n) {
int k;
for (k = INT_MIN; k <= INT_MAX; ++k) {
if (n == 2 * k) {
return 1;
}
}
return 0;
}
char odd (int n) {
int k;
for (k = INT_MIN; k <= INT_MAX; ++k) {
if (n == 2 * k + 1) {
return 1;
}
}
return 0;
}
C-tamsayılarının olası değerleri göstermesine izin verin int
belirli bir C derlemesindeki . (C tam sayılarının tam sayıların bir alt kümesi olduğuna dikkat edin.)
Şimdi, C tamsayılarındaki belirli bir n için karşılık gelen tamsayı k'nın C tamsayılarında bulunmayabileceğinden endişe edilebilir. Ancak küçük bir kanıtla, tüm tamsayılar için n, | n | <= | 2n | (*), burada | n | "n pozitifse n ve aksi takdirde -n" dir. Başka bir deyişle, tamsayılardaki tüm n için aşağıdaki asgari tutardan en az biri (tam olarak ya vakalar (1 ve 2) ya da vakalar (3 ve 4) aslında ama bunu burada kanıtlamayacağım):
Durum 1: n <= 2n.
Durum 2: -n <= -2n.
Durum 3: -n <= 2n.
Durum 4: n <= -2n.
Şimdi 2k = n al. (N bile olsa böyle bir ak var, ama burada kanıtlayamayacağım. Eğer n bile değilse, döngü even
yine de erken dönemiyor, bu yüzden önemli değil.) Ama bu k <n 0 ile (*) değil ve (burada tekrar kanıtlanmadı) tüm m için, 2m = z tamsayılarındaki z, m'nin m'ye eşit olmadığı anlamına gelir, m 0 değildir. yani 0 bile yapılır (n = 0 ise 0 C-tamsayılarındadır, çünkü n fonksiyonda C-tamsayısındadır)even
, dolayısıyla k = 0 C-tamsayılarındadır). Bu nedenle, C tamsayılarındaki bu ak, n eşitse, C tamsayılarındaki n için bulunur.
Benzer bir argüman, eğer n tuhafsa, C-tamsayılarında n = 2k + 1 olacak şekilde ak olduğunu gösterir.
Dolayısıyla fonksiyonları even
ve odd
burada sunulan tüm C-tamsayılar için düzgün çalışacaktır.
i % 2
çok daha küçük ve muhtemelen daha verimlidir.
%2
tüm tamsayılar için çalışır.
// C#
bool isEven = ((i % 2) == 0);
typedef
ya #define
falan.
İşte Java'da bir cevap:
public static boolean isEven (Integer Number) {
Pattern number = Pattern.compile("^.*?(?:[02]|8|(?:6|4))$");
String num = Number.toString(Number);
Boolean numbr = new Boolean(number.matcher(num).matches());
return numbr.booleanValue();
}
Bunu dene: return (((a>>1)<<1) == a)
Misal:
a = 10101011
-----------------
a>>1 --> 01010101
a<<1 --> 10101010
b = 10011100
-----------------
b>>1 --> 01001110
b<<1 --> 10011100
Bu oldukça eğlenceli tartışmayı okurken, ana döngü içinde tek ve çift sayıları test eden gerçek dünyaya, zamana duyarlı bir işleve sahip olduğumu hatırladım. StackOverflow üzerinde başka bir yerde yayınlanan aşağıdaki gibi bir tamsayı güç işlevidir. Kriterler oldukça şaşırtıcıydı. En azından bu gerçek dünya işlevinde, modulo daha yavaş ve önemli ölçüde. Kazanan, modulo zamanının% 67'sini gerektiren geniş bir farkla, bir veya (|) yaklaşımıdır ve bu sayfanın başka bir yerinde bulunamaz.
static dbl IntPow(dbl st0, int x) {
UINT OrMask = UINT_MAX -1;
dbl st1=1.0;
if(0==x) return (dbl)1.0;
while(1 != x) {
if (UINT_MAX == (x|OrMask)) { // if LSB is 1...
//if(x & 1) {
//if(x % 2) {
st1 *= st0;
}
x = x >> 1; // shift x right 1 bit...
st0 *= st0;
}
return st1 * st0;
}
300 milyon döngü için kıyaslama zamanlamaları aşağıdaki gibidir.
3.962 | ve maske yaklaşımı
4.851 & yaklaşımı
5.850% yaklaşımı
Teori ya da bir montaj dili listesi düşünen insanlar için bu gibi argümanlar ortaya koyar, bu bir uyarıcı masal olmalıdır. Cennette ve dünyada, Horatio'da, felsefenizde hayal edilenden daha fazla şey vardır.
unsigned x
olarak x = x >> 1;
tanımlandığında daha iyi tanımlanır davranış x < 0
. Nedeni belirsiz x
ve OrMask
türü farklı. Bir while(x)
test kullanarak yeniden yazmak için yeterince basit .
% 2
kasayı bitsel olarak kullanarak derleyecek kadar akıllı olmalıdır &
. Bunu sadece test ettim ve sonuçlar tamamen aynı (VS2015, Release, tüm optimizasyonlarla, x86 ve x64 ile derlenir). Kabul edilen cevap bunu GCC için de belirtmektedir (2008'de yazılmıştır).
or
bir daha hızlı olacağını öncül and
oldukça düşük olmasıdır. Böyle garip bir platform / derleyici kombo olsa bile (ve kıyaslama yapmak için kullanılan kodu da göndermemiş olsanız bile), aynı davranacak diğer derleyicilere bağlı olarak kötü bir optimizasyon bahsi olacaktır. Yazdığım gibi, bunun hangi platform / derleyicinin test edildiğini merak ediyorum , çünkü doğru bir şekilde ölçülmediğinden neredeyse eminim.
Bu, @RocketRoy ile cevabı hakkındaki tartışmanın devamı niteliğindedir. , ancak bu sonuçları karşılaştırmak isteyen herkes için yararlı olabilir.
tl; dr Gördüğüm kadarıyla, Roy'un yaklaşımı ( (0xFFFFFFFF == (x | 0xFFFFFFFE)
) tamamen üzere optimize edilmemiştir x & 1
olarakmod
yaklaşımla, ama pratikte çalışan süreleri her durumda eşit çıkmak gerekir.
İlk olarak derlenmiş çıktıyı Compiler Explorer kullanarak karşılaştırdım :
Test edilen fonksiyonlar:
int isOdd_mod(unsigned x) {
return (x % 2);
}
int isOdd_and(unsigned x) {
return (x & 1);
}
int isOdd_or(unsigned x) {
return (0xFFFFFFFF == (x | 0xFFFFFFFE));
}
CLang 3.9.0 -O3 ile:
isOdd_mod(unsigned int): # @isOdd_mod(unsigned int)
and edi, 1
mov eax, edi
ret
isOdd_and(unsigned int): # @isOdd_and(unsigned int)
and edi, 1
mov eax, edi
ret
isOdd_or(unsigned int): # @isOdd_or(unsigned int)
and edi, 1
mov eax, edi
ret
-O3 ile GCC 6.2:
isOdd_mod(unsigned int):
mov eax, edi
and eax, 1
ret
isOdd_and(unsigned int):
mov eax, edi
and eax, 1
ret
isOdd_or(unsigned int):
or edi, -2
xor eax, eax
cmp edi, -1
sete al
ret
CLang'a kadar şapkalar, üç vakanın da işlevsel olarak eşit olduğunu fark etti. Bununla birlikte, Roy'un yaklaşımı GCC'de optimize edilmediğinden YMMV.
Visual Studio ile benzer; bu üç işlev için sökme Bülteni x64 (VS2015) incelendiğinde, karşılaştırma bölümünün "mod" ve "ve" kasaları için eşit olduğunu ve Roy'un "veya" kutusu için biraz daha büyük olduğunu görebiliyordum:
// x % 2
test bl,1
je (some address)
// x & 1
test bl,1
je (some address)
// Roy's bitwise or
mov eax,ebx
or eax,0FFFFFFFEh
cmp eax,0FFFFFFFFh
jne (some address)
Ancak, bu üç seçeneği karşılaştırmak için gerçek bir kıyaslama çalıştırdıktan sonra (düz mod, bitsel veya bitsel ve), sonuçlar tamamen eşitti (yine, Visual Studio 2005 x86 / x64, Release build, hata ayıklayıcı eklenmedi).
Sürüm montajı, test
talimatlar and
ve mod
vakalar için talimatlar kullanırken Roy'un davası cmp eax,0FFFFFFFFh
yaklaşımı kullanır , ancak pratik olarak hiçbir fark olmaması için ağır bir şekilde açılmış ve optimize edilmiştir.
20 çalıştırmadan sonraki sonuçlarım (i7 3610QM, Windows 10 güç planı Yüksek Performans olarak ayarlandı):
[Test: Düz mod 2] ORTALAMA SÜRESİ: 689,29 ms (Nispi fark: +% 0,000) [Test: Bitsel veya] ORTALAMA SÜRESİ: 689,63 ms (Nispi fark: +% 0,048) [Test: Bitsel ve] ORTALAMA SÜRESİ: 687,80 ms (Bağıl fark: -0.217%)
Bu seçenekler arasındaki fark% 0.3'ten azdır, bu nedenle montajın her durumda eşit olduğu açıktır.
İşte kimse denemek istiyorsa kod, ben sadece Windows üzerinde test bir uyarı ile ( tanım için #if LINUX
koşullu kontrol edin get_time
ve gerekirse bu cevap alınan ).
#include <stdio.h>
#if LINUX
#include <sys/time.h>
#include <sys/resource.h>
double get_time()
{
struct timeval t;
struct timezone tzp;
gettimeofday(&t, &tzp);
return t.tv_sec + t.tv_usec*1e-6;
}
#else
#include <windows.h>
double get_time()
{
LARGE_INTEGER t, f;
QueryPerformanceCounter(&t);
QueryPerformanceFrequency(&f);
return (double)t.QuadPart / (double)f.QuadPart * 1000.0;
}
#endif
#define NUM_ITERATIONS (1000 * 1000 * 1000)
// using a macro to avoid function call overhead
#define Benchmark(accumulator, name, operation) { \
double startTime = get_time(); \
double dummySum = 0.0, elapsed; \
int x; \
for (x = 0; x < NUM_ITERATIONS; x++) { \
if (operation) dummySum += x; \
} \
elapsed = get_time() - startTime; \
accumulator += elapsed; \
if (dummySum > 2000) \
printf("[Test: %-12s] %0.2f ms\r\n", name, elapsed); \
}
void DumpAverage(char *test, double totalTime, double reference)
{
printf("[Test: %-12s] AVERAGE TIME: %0.2f ms (Relative diff.: %+6.3f%%)\r\n",
test, totalTime, (totalTime - reference) / reference * 100.0);
}
int main(void)
{
int repeats = 20;
double runningTimes[3] = { 0 };
int k;
for (k = 0; k < repeats; k++) {
printf("Run %d of %d...\r\n", k + 1, repeats);
Benchmark(runningTimes[0], "Plain mod 2", (x % 2));
Benchmark(runningTimes[1], "Bitwise or", (0xFFFFFFFF == (x | 0xFFFFFFFE)));
Benchmark(runningTimes[2], "Bitwise and", (x & 1));
}
{
double reference = runningTimes[0] / repeats;
printf("\r\n");
DumpAverage("Plain mod 2", runningTimes[0] / repeats, reference);
DumpAverage("Bitwise or", runningTimes[1] / repeats, reference);
DumpAverage("Bitwise and", runningTimes[2] / repeats, reference);
}
getchar();
return 0;
}
Bunun sadece sözdizimsel şeker olduğunu ve sadece .net'te uygulanabileceğini biliyorum ama ya uzatma yöntemi ...
public static class RudiGroblerExtensions
{
public static bool IsOdd(this int i)
{
return ((i % 2) != 0);
}
}
Şimdi aşağıdakileri yapabilirsiniz
int i = 5;
if (i.IsOdd())
{
// Do something...
}
"Yaratıcı ama kafa karıştırıcı kategorisinde" teklif ediyorum:
int isOdd(int n) { return n ^ n * n ? isOdd(n * n) : n; }
Bu temadaki Microsoft C ++ 'a özgü bir varyant:
__declspec(naked) bool __fastcall isOdd(const int x)
{
__asm
{
mov eax,ecx
mul eax
mul eax
mul eax
mul eax
mul eax
mul eax
ret
}
}
Bitsel yöntem, tamsayının iç gösterimine bağlıdır. Modulo, bir modulo operatörünün bulunduğu her yerde çalışacaktır. Örneğin, bazı sistemler etiketleme için (dinamik diller gibi) aslında düşük seviye bitleri kullanır, bu nedenle raw x & 1 aslında bu durumda çalışmaz.
IsOdd (int x) {dönüş doğru; }
Doğruluk kanıtı - tüm pozitif tamsayıların kümesini göz önünde bulundurun ve garip olmayan boş olmayan bir tamsayılar kümesi olduğunu varsayalım. Pozitif tamsayılar iyi sıralandığından, kendi başına oldukça garip olmayan en küçük tek bir sayı olacaktır, bu yüzden açıkça bu sayı kümede olamaz. Bu nedenle bu küme boş bırakılamaz. En büyük tek sayı için arama dışında negatif tamsayıları tekrarlayın
Bazı insanların gönderdiği gibi, bunu yapmanın birçok yolu vardır. Bu web sitesine göre , en hızlı yol modül operatörüdür:
if (x % 2 == 0)
total += 1; //even number
else
total -= 1; //odd number
Bununla birlikte, yukarıdaki ortak modül işleminden daha yavaş çalışan, yazar tarafından işaretlenmiş başka bir kod :
if ((x & 1) == 0)
total += 1; //even number
else
total -= 1; //odd number
System.Math.DivRem((long)x, (long)2, out outvalue);
if ( outvalue == 0)
total += 1; //even number
else
total -= 1; //odd number
if (((x / 2) * 2) == x)
total += 1; //even number
else
total -= 1; //odd number
if (((x >> 1) << 1) == x)
total += 1; //even number
else
total -= 1; //odd number
while (index > 1)
index -= 2;
if (index == 0)
total += 1; //even number
else
total -= 1; //odd number
tempstr = x.ToString();
index = tempstr.Length - 1;
//this assumes base 10
if (tempstr[index] == '0' || tempstr[index] == '2' || tempstr[index] == '4' || tempstr[index] == '6' || tempstr[index] == '8')
total += 1; //even number
else
total -= 1; //odd number
Kaç kişi Math.System.DivRem yöntemini biliyordu ya da neden kullanıyorlar ??
Çalışmalarımız sırasında çok boole cebiri yapmayanlarımız için bitsel operatör yöntemi hakkında daha fazla ayrıntı vermek için burada bir açıklama var. Muhtemelen OP için çok fazla faydası yok, ancak NUMBER & 1'in neden çalıştığını açıklamak gibi hissettim.
Lütfen yukarıda yanıtladığı gibi, negatif sayıların temsil edilme şeklinin bu yöntemin çalışmasını durdurabileceğini unutmayın. Aslında modulo operatör yöntemini bile kırabilir, çünkü her dil negatif işlenenlerle nasıl başa çıktığı konusunda farklılık gösterebilir.
Ancak NUMBER'in her zaman olumlu olacağını biliyorsanız, bu iyi çalışır.
Yukarıdaki Tooony'nin, ikili (ve denary) sadece son basamağın önemli olduğuna işaret ettiği gibi.
Bir boole mantığı VE geçidi, her iki girişin de 1'in döndürülmesi için 1 (veya yüksek voltaj) olması gerektiğini belirtir.
1 & 0 = 0.
0 & 1 = 0.
0 & 0 = 0.
1 & 1 = 1.
İkili olarak herhangi bir sayıyı temsil ediyorsanız (burada 8 bitlik bir gösterim kullandım), tek sayıların sonunda 1, hatta sayıların 0 vardır.
Örneğin:
1 = 00000001
2 = 00000010
3 = 00000011
4 = 00000100
Herhangi bir sayı alır ve bitsel AND (& in java) kullanırsanız 1 ile 00000001, = 1 döndürür, yani sayı gariptir. Veya 00000000 = 0, yani sayı çifttir.
Örneğin
Garip?
1 & 1 =
00000001 ve
00000001 =
00000001 <- Oran
2 & 1 =
00000010 ve
00000001 =
00000000 <- Çift
54 ve 1 =
00000001 ve
00110110 =
00000000 <- Çift
Bu yüzden bu işe yarar:
if(number & 1){
//Number is odd
} else {
//Number is even
}
Gerekirse özür dilerim.
Sıfır Eşlik Sayısı | sıfır http://tinyurl.com/oexhr3k
Python kod dizisi.
# defining function for number parity check
def parity(number):
"""Parity check function"""
# if number is 0 (zero) return 'Zero neither ODD nor EVEN',
# otherwise number&1, checking last bit, if 0, then EVEN,
# if 1, then ODD.
return (number == 0 and 'Zero neither ODD nor EVEN') \
or (number&1 and 'ODD' or 'EVEN')
# cycle trough numbers from 0 to 13
for number in range(0, 14):
print "{0:>4} : {0:08b} : {1:}".format(number, parity(number))
Çıktı:
0 : 00000000 : Zero neither ODD nor EVEN
1 : 00000001 : ODD
2 : 00000010 : EVEN
3 : 00000011 : ODD
4 : 00000100 : EVEN
5 : 00000101 : ODD
6 : 00000110 : EVEN
7 : 00000111 : ODD
8 : 00001000 : EVEN
9 : 00001001 : ODD
10 : 00001010 : EVEN
11 : 00001011 : ODD
12 : 00001100 : EVEN
13 : 00001101 : ODD
I execute this code for ODD & EVEN:
#include <stdio.h>
int main()
{
int number;
printf("Enter an integer: ");
scanf("%d", &number);
if(number % 2 == 0)
printf("%d is even.", number);
else
printf("%d is odd.", number);
}
Tartışma uğruna ...
Çift veya tek olup olmadığını görmek için herhangi bir sayıdaki son basamağa bakmanız yeterlidir. İmzalı, imzasız, pozitif, negatif - hepsi bu konuda aynı. Yani bu her yerde çalışmalı: -
void tellMeIfItIsAnOddNumberPlease(int iToTest){
int iLastDigit;
iLastDigit = iToTest - (iToTest / 10 * 10);
if (iLastDigit % 2 == 0){
printf("The number %d is even!\n", iToTest);
} else {
printf("The number %d is odd!\n", iToTest);
}
}
Buradaki anahtar üçüncü kod satırındadır, bölüm operatörü bir tamsayı bölümü gerçekleştirir, böylece sonuç sonucun kesir kısmını kaçırır. Yani örneğin 222/10 sonuç olarak 22 verecektir. Sonra tekrar 10 ile çarpın ve 220'niz var. Orijinal 222'den çıkarın ve büyü ile orijinal sayının son basamağıyla aynı sayı olan 2 ile bitirin. ;-) Parantez bize hesaplamanın yapıldığı sırayı hatırlatmak için var. Önce bölümü ve çarpımı yapın, ardından sonucu orijinal sayıdan çıkarın. Bunları dışarıda bırakabiliriz, çünkü bölünme ve çarpma için öncelik çıkarma işleminden daha yüksektir, ancak bu bize "daha okunabilir" kod verir.
Eğer isteseydik hepsini okunamaz hale getirebilirdik. Modern bir derleyici için hiçbir fark yaratmaz: -
printf("%d%s\n",iToTest,0==(iToTest-iToTest/10*10)%2?" is even":" is odd");
Ancak, kodun gelecekte sürdürülmesini zorlaştıracaktır. Tek sayılar için metni "çift değil" olarak değiştirmek istediğinizi düşünün. Sonra başka biri daha sonra hangi değişiklikleri yaptığınızı öğrenmek ve bir svn diff veya benzeri yapmak istiyorum ...
Taşınabilirlik hakkında değil, hız hakkında daha fazla endişeleniyorsanız, en az önemli bite bakabilirsiniz. Bu bit 1 olarak ayarlanırsa, tek bir sayıdır, 0 ise çift bir sayıdır. Küçük bir endian sisteminde, Intel'in x86 mimarisi gibi şöyle bir şey olurdu:
if (iToTest & 1) {
// Even
} else {
// Odd
}
Verimli olmak istiyorsanız, bitsel operatörler ( x & 1
) kullanın , ancak okunabilir olmak istiyorsanız modulo 2 ( x % 2
) kullanın
%
. Okunabilir olmasını istiyorsanız kullanın %
. Hmmm, burada bir model görüyorum.
Çift veya tek kontrol etmek basit bir iştir.
Tam olarak 2'ye bölünebilen herhangi bir sayının çift sayı olan tek sayı olduğunu biliyoruz.
Sadece herhangi bir sayının bölünebilirliğini kontrol etmemiz ve %
operatörü kullandığımız bölünebilirliği kontrol etmemiz gerekir
Aksi takdirde tek tutam kullanarak kontrol etme
if(num%2 ==0)
{
printf("Even");
}
else
{
printf("Odd");
}
C programı çift veya tek kullanarak kullanarak kontrol etmek
Koşullu / Üçlü işleci kullanma
(num%2 ==0) printf("Even") : printf("Odd");
C programı koşullu operatör kullanarak çift veya tek kontrol etmek .
Bitwise operatörünü kullanma
if(num & 1)
{
printf("Odd");
}
else
{
printf("Even");
}
!(i%2) / i%2 == 0
int isOdd(int n)
{
return n & 1;
}
Kod, eğer tamsayının son bitini kontrol eder 1 Binary
Binary : Decimal
-------------------
0000 = 0
0001 = 1
0010 = 2
0011 = 3
0100 = 4
0101 = 5
0110 = 6
0111 = 7
1000 = 8
1001 = 9
and so on...
En doğru bitin Tek sayılar için her zaman 1 olduğuna dikkat edin .
& bizim en sağdaki bit lojik AND operatörü kontrolleri dönüş hattı durum 1 ise
Biz karşılaştırdığımızda n ile 1 hangi yollarla 0001
ikilik sistemde (sıfırların sayısı önemli değil).
o zaman sadece 1 bayt büyüklüğünde n tamsayısına sahip olduğumuzu düşünelim .
8-bit / 8-ikili basamaklarla temsil edilir.
İnt Eğer n oldu 7 ve biz ile karşılaştırın 1 , Sanki
7 (1-byte int)| 0 0 0 0 0 1 1 1
&
1 (1-byte int)| 0 0 0 0 0 0 0 1
********************************************
Result | F F F F F F F T
Hangi F yanlış, T de doğrudur.
İkisi de doğruysa en sağdaki biti karşılaştırır . Yani, otomajik
7 & 1
olarak T rue.
İkili n & 1
olarak n & 2
hangi 2'yi temsil ettiğinizi değiştirin 0010
.
Bitsel işlemlere yeni başlıyorsanız onaltılık gösterimi kullanmanızı öneririm
return n & 1;
>> return n & 0x01;
.