30. juli 2004 - 18:19
Der er
18 kommentarer og 1 løsning
Position af bit
Hej alle sammen Jeg har et lille problem ang. hastighed. Jeg har en integer, og i denne er der eet bit sat. Jeg vil gerne vide paa hvilken position bittet er sat. Eks: integer vaerdi|bit streng|position 1|1|1 4|100|3 64|1000000|7 Findes der en let funktion til dette, eller skal man goere noget a la: int i = 1; int search = 64; while(true) { if(search == 1) break; search = search >> 1; i++; }
Annonceindlæg tema
Forsvar & beredskab
Cybersikkerhed, realtidsdata og robuste it-systemer er blevet fundamentet for moderne forsvar.
Du har allerede en simpel løkke. Jeg mener ikke at der er noget indbygget i .NET for dette. Du kunne formentligt speede det marginalt op ved at lave en binær søgning i.s.f. en sekventiel søgning (< 65536 så er det en af de laveste 16 bits der er sat, < 256 så er det en af de laveste 8 bits der er sat).
Det er noget hurtigere. Leg selv videre med: using System; class MainClass { public static int ffs1(uint v) { uint tmp = v; for(int i = 1; i <= 32; i++) { if(tmp == 1) return i; tmp >>= 1; } return -1; } public static int ffs2(uint v) { if(v < 0x00010000) { if(v < 0x00000100) { if(v < 0x00000010) { if(v < 0x00000004) { if(v < 0x00000002) { return 1; } else { return 2; } } else { if(v < 0x00000008) { return 3; } else { return 4; } } } else { if(v < 0x00000040) { if(v < 0x00000020) { return 5; } else { return 6; } } else { if(v < 0x00000080) { return 7; } else { return 8; } } } } else { if(v < 0x00001000) { if(v < 0x00000400) { if(v < 0x00000200) { return 9; } else { return 10; } } else { if(v < 0x00000800) { return 11; } else { return 12; } } } else { if(v < 0x00004000) { if(v < 0x00002000) { return 13; } else { return 14; } } else { if(v < 0x00008000) { return 15; } else { return 16; } } } } } else { if(v < 0x01000000) { if(v < 0x00100000) { if(v < 0x00040000) { if(v < 0x00020000) { return 17; } else { return 18; } } else { if(v < 0x00080000) { return 19; } else { return 20; } } } else { if(v < 0x00400000) { if(v < 0x00200000) { return 21; } else { return 22; } } else { if(v < 0x00800000) { return 23; } else { return 24; } } } } else { if(v < 0x10000000) { if(v < 0x04000000) { if(v < 0x02000000) { return 25; } else { return 26; } } else { if(v < 0x08000000) { return 27; } else { return 28; } } } else { if(v < 0x40000000) { if(v < 0x20000000) { return 29; } else { return 30; } } else { if(v < 0x80000000) { return 31; } else { return 32; } } } } } } private const int N = 10000000; public static void Main(string[] args) { for(int i = 0; i < 32; i++) { Console.WriteLine(ffs1((uint)(1 << i)) + " " + ffs2((uint)(1 << i))); } int res = 0; long t1 = DateTime.Now.Ticks; for(int i = 0; i < N; i++) { res = ffs1(65536); } long t2 = DateTime.Now.Ticks; Console.WriteLine(res + " : " + (t2 - t1)); long t3 = DateTime.Now.Ticks; for(int i = 0; i < N; i++) { res = ffs2(65536); } long t4 = DateTime.Now.Ticks; Console.WriteLine(res + " : " + (t4 - t3)); } }
Men det gør ikke koden mindre ! :-)
Og et svar såfremt ingen har bedre ideer.
ok, ja, jeg regnede heller ikke med at der var andre svar. Jeg havde haabet paa at der var noget nemt der kunne bruges og som fyldte en linie kode. Men nej....
Den der binære søgning er tilsyneladende den hurtigste.
using System; class MainClass { public static int ffs1(uint v) { uint tmp = v; for(int i = 1; i <= 32; i++) { if(tmp == 1) return i; tmp >>= 1; } return -1; } public static int ffs2(uint v) { uint tmp = v; if(tmp == 0) { return -1; } int i = 1; while((tmp & 1) == 0) { tmp >>= 1; i++; } return i; } private static int[] table = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 }; public static int ffs3(uint v) { uint a, x; x = (uint)(v & -v); a = (uint)((x <= 0xFFFF) ? ((x <= 0xFF) ? 0 : 8) : ((x <= 0xFFFFFF) ? 16 : 24)); return (int)(table[x >> (int)a] + a); } public static int ffs4(uint v) { if(v < 0x00010000) { if(v < 0x00000100) { if(v < 0x00000010) { if(v < 0x00000004) { if(v < 0x00000002) { return 1; } else { return 2; } } else { if(v < 0x00000008) { return 3; } else { return 4; } } } else { if(v < 0x00000040) { if(v < 0x00000020) { return 5; } else { return 6; } } else { if(v < 0x00000080) { return 7; } else { return 8; } } } } else { if(v < 0x00001000) { if(v < 0x00000400) { if(v < 0x00000200) { return 9; } else { return 10; } } else { if(v < 0x00000800) { return 11; } else { return 12; } } } else { if(v < 0x00004000) { if(v < 0x00002000) { return 13; } else { return 14; } } else { if(v < 0x00008000) { return 15; } else { return 16; } } } } } else { if(v < 0x01000000) { if(v < 0x00100000) { if(v < 0x00040000) { if(v < 0x00020000) { return 17; } else { return 18; } } else { if(v < 0x00080000) { return 19; } else { return 20; } } } else { if(v < 0x00400000) { if(v < 0x00200000) { return 21; } else { return 22; } } else { if(v < 0x00800000) { return 23; } else { return 24; } } } } else { if(v < 0x10000000) { if(v < 0x04000000) { if(v < 0x02000000) { return 25; } else { return 26; } } else { if(v < 0x08000000) { return 27; } else { return 28; } } } else { if(v < 0x40000000) { if(v < 0x20000000) { return 29; } else { return 30; } } else { if(v < 0x80000000) { return 31; } else { return 32; } } } } } } private const int N = 10000000; public static void Main(string[] args) { for(int i = 0; i < 32; i++) { Console.WriteLine(ffs1((uint)(1 << i)) + " " + ffs2((uint)(1 << i)) + " " + ffs3((uint)(1 << i)) + " " + ffs4((uint)(1 << i))); } int res = 0; long t1 = DateTime.Now.Ticks; for(int i = 0; i < N; i++) { res = ffs1(65536); } long t2 = DateTime.Now.Ticks; Console.WriteLine("alg 1 : " + (t2 - t1)); long t3 = DateTime.Now.Ticks; for(int i = 0; i < N; i++) { res = ffs2(65536); } long t4 = DateTime.Now.Ticks; Console.WriteLine("alg 2 : " + (t4 - t3)); long t5 = DateTime.Now.Ticks; for(int i = 0; i < N; i++) { res = ffs3(65536); } long t6 = DateTime.Now.Ticks; Console.WriteLine("alg 3 : " + (t6 - t5)); long t7 = DateTime.Now.Ticks; for(int i = 0; i < N; i++) { res = ffs4(65536); } long t8 = DateTime.Now.Ticks; Console.WriteLine("alg 4 : " + (t8 - t7)); } }
alg 1 : 8437500 alg 2 : 5156250 alg 3 : 2187500 alg 4 : 1250000
02. august 2004 - 17:06
#9
excellente... jeg takker mange gange.
04. august 2004 - 18:32
#10
Jeg har en anden loesning, har dog ikke checket hastigheden endnu: System.COllections.Hashtable table = new .... table.add(0, 0); table.add(1, 1); table.add(2, 2); table.add(4, 3); table.add(8, 4); osv.... int bitnummerSat = (int)table[integervalueMedEtBitSat]
04. august 2004 - 19:26
#11
Ideen er genial. Implementeringen er la la.
04. august 2004 - 19:26
#12
private static Hashtable htable = new Hashtable(); static MainClass() { for(int i = 0; i < 32; i++) { htable.Add((UInt32)(1 << i), (Int32)(i + 1)); } } public static int ffs5(uint v) { return (int)htable[v]; }
04. august 2004 - 19:27
#13
alg 1 : 13719728 alg 2 : 8011520 alg 3 : 3204608 alg 4 : 2503600 alg 5 : 33648384 alg 6 : 400576
04. august 2004 - 19:28
#14
Vi ser at alg 5 som er Hashtable er den langsomste af alle. Men i en lettere ændret udgave alg 6 så er den faktisk suverænt den hurtigste.
04. august 2004 - 19:28
#15
private static int[] ztable = { -1, 1, 2, 27, 3, 24, 28, -1, 4, 17, 25, 31, 29, 12, -1, 14, 5, 8, 18, -1, 26, 23, 32, 16, 30, 11, 13, 7, -1, 22, 15, 10, 6, 21, 9, 20, 19 }; public static int ffs6(uint v) { return ztable[v % 37];; }
04. august 2004 - 19:29
#16
Hvis nogen ikke kan få tiderne til at stemme med de forrige, så det fordi det her er på en langsommere maskine.
04. august 2004 - 19:29
#17
Hele koden: using System; using System.Collections; class MainClass { public static int ffs1(uint v) { uint tmp = v; for(int i = 1; i <= 32; i++) { if(tmp == 1) return i; tmp >>= 1; } return -1; } public static int ffs2(uint v) { uint tmp = v; if(tmp == 0) { return -1; } int i = 1; while((tmp & 1) == 0) { tmp >>= 1; i++; } return i; } private static int[] table = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 }; public static int ffs3(uint v) { uint a, x; x = (uint)(v & -v); a = (uint)((x <= 0xFFFF) ? ((x <= 0xFF) ? 0 : 8) : ((x <= 0xFFFFFF) ? 16 : 24)); return (int)(table[x >> (int)a] + a); } public static int ffs4(uint v) { if(v < 0x00010000) { if(v < 0x00000100) { if(v < 0x00000010) { if(v < 0x00000004) { if(v < 0x00000002) { return 1; } else { return 2; } } else { if(v < 0x00000008) { return 3; } else { return 4; } } } else { if(v < 0x00000040) { if(v < 0x00000020) { return 5; } else { return 6; } } else { if(v < 0x00000080) { return 7; } else { return 8; } } } } else { if(v < 0x00001000) { if(v < 0x00000400) { if(v < 0x00000200) { return 9; } else { return 10; } } else { if(v < 0x00000800) { return 11; } else { return 12; } } } else { if(v < 0x00004000) { if(v < 0x00002000) { return 13; } else { return 14; } } else { if(v < 0x00008000) { return 15; } else { return 16; } } } } } else { if(v < 0x01000000) { if(v < 0x00100000) { if(v < 0x00040000) { if(v < 0x00020000) { return 17; } else { return 18; } } else { if(v < 0x00080000) { return 19; } else { return 20; } } } else { if(v < 0x00400000) { if(v < 0x00200000) { return 21; } else { return 22; } } else { if(v < 0x00800000) { return 23; } else { return 24; } } } } else { if(v < 0x10000000) { if(v < 0x04000000) { if(v < 0x02000000) { return 25; } else { return 26; } } else { if(v < 0x08000000) { return 27; } else { return 28; } } } else { if(v < 0x40000000) { if(v < 0x20000000) { return 29; } else { return 30; } } else { if(v < 0x80000000) { return 31; } else { return 32; } } } } } } private static Hashtable htable = new Hashtable(); static MainClass() { for(int i = 0; i < 32; i++) { htable.Add((UInt32)(1 << i), (Int32)(i + 1)); } } public static int ffs5(uint v) { return (int)htable[v]; } private static int[] ztable = { -1, 1, 2, 27, 3, 24, 28, -1, 4, 17, 25, 31, 29, 12, -1, 14, 5, 8, 18, -1, 26, 23, 32, 16, 30, 11, 13, 7, -1, 22, 15, 10, 6, 21, 9, 20, 19 }; public static int ffs6(uint v) { return ztable[v % 37];; } private const int N = 10000000; public static void Main(string[] args) { for(int i = 0; i < 32; i++) { Console.WriteLine(ffs1((uint)(1 << i)) + " " + ffs2((uint)(1 << i)) + " " + ffs3((uint)(1 << i)) + " " + ffs4((uint)(1 << i)) + " " + ffs5((uint)(1 << i)) + " " + ffs6((uint)(1 << i))); } int res = 0; long t1 = DateTime.Now.Ticks; for(int i = 0; i < N; i++) { res = ffs1(65536); } long t2 = DateTime.Now.Ticks; Console.WriteLine("alg 1 : " + (t2 - t1)); long t3 = DateTime.Now.Ticks; for(int i = 0; i < N; i++) { res = ffs2(65536); } long t4 = DateTime.Now.Ticks; Console.WriteLine("alg 2 : " + (t4 - t3)); long t5 = DateTime.Now.Ticks; for(int i = 0; i < N; i++) { res = ffs3(65536); } long t6 = DateTime.Now.Ticks; Console.WriteLine("alg 3 : " + (t6 - t5)); long t7 = DateTime.Now.Ticks; for(int i = 0; i < N; i++) { res = ffs4(65536); } long t8 = DateTime.Now.Ticks; Console.WriteLine("alg 4 : " + (t8 - t7)); long t9 = DateTime.Now.Ticks; for(int i = 0; i < N; i++) { res = ffs5(65536); } long t10 = DateTime.Now.Ticks; Console.WriteLine("alg 5 : " + (t10 - t9)); long t11 = DateTime.Now.Ticks; for(int i = 0; i < N; i++) { res = ffs6(65536); } long t12 = DateTime.Now.Ticks; Console.WriteLine("alg 6 : " + (t12 - t11)); } }
06. august 2004 - 22:25
#18
Hvordan kom du lige paa ffs6, er der evt en forklaring paa hvorfor og hvordan det virker?
06. august 2004 - 22:39
#19
Ideen med hash er god. Hashtable har alt for meget overhead. Men jeg var overbevist om at man kunne lave en "hurtig hashing" optimeret til lige netop dette problem. Det er meget normalt at bruge modulus til hashing, så jeg lavede et lille program som fandt det mindste tal hvor 2^n % x gav forskellige tal for alle n=0..31, det tal var 37 og så var det bare at konstruere et array som returnerede korrekt bit numme rudfra % 37.
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.