Günlük (2 tabanı) işlevini yazmanın herhangi bir yolu var mı?
C dilinin 2 yerleşik işlevi vardır - >>
1. loge baz olan.
2. log10taban 10;
Ama 2 tabanının log fonksiyonuna ihtiyacım var, bunu nasıl hesaplayacağım.
Günlük (2 tabanı) işlevini yazmanın herhangi bir yolu var mı?
C dilinin 2 yerleşik işlevi vardır - >>
1. loge baz olan.
2. log10taban 10;
Ama 2 tabanının log fonksiyonuna ihtiyacım var, bunu nasıl hesaplayacağım.
Yanıtlar:
Basit matematik:
günlük 2 ( x ) = günlük y ( x ) / günlük y (2)
burada y herhangi bir şey olabilir, standart günlük işlevleri için 10 veya e'dir .
C99 sahiptir log2(yanı sıra log2fve log2lfloat ve long double için).
İntegral bir sonuç arıyorsanız, değerdeki en yüksek bit setini belirleyebilir ve konumunu döndürebilirsiniz.
Integer.highestOneBit(int)):i |= (i >> 1); i |= (i >> 2); i |= (i >> 4); i |= (i >> 8); i |= (i >> 16); return i - (i >>> 1);
while (i >>= 1) { ++l; }
i>>32. Ancak Java yalnızca 32 bitlik girişlere sahip olduğu için sorun değil. C / C ++ için dikkate alınması gerekir.
#define M_LOG2E 1.44269504088896340736 // log2(e)
inline long double log2(const long double x){
return log(x) * M_LOG2E;
}
(çarpma, bölmeden daha hızlı olabilir)
Http://en.wikipedia.org/wiki/Logarithm adresinde belirtildiği gibi :
logb(x) = logk(x) / logk(b)
Bu şu anlama gelir:
log2(x) = log10(x) / log10(2)
log()uygulamanın kaynağını asla görmediğinden, bunu yapmayacaktır. Benim hatam.
log10()C standardında tanımlanmış bir işlev olduğu için, derleyici, sonucun önceden hesaplanması da dahil olmak üzere "özel" olarak ele almakta özgürdür, bence @ Johannes'in önerisi?
log10(2)bir sabit ile değiştiriliyor .
Hızlı yapmak istiyorsanız, Bit Twiddling Hacks'teki gibi bir arama tablosu kullanabilirsiniz (yalnızca tamsayı log2).
uint32_t v; // find the log base 2 of 32-bit v
int r; // result goes here
static const int MultiplyDeBruijnBitPosition[32] =
{
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
};
v |= v >> 1; // first round down to one less than a power of 2
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
r = MultiplyDeBruijnBitPosition[(uint32_t)(v * 0x07C4ACDDU) >> 27];
Ek olarak, derleyicilerinizin yerleşik yöntemlerine de bir göz atmalısınız, _BitScanReversehangisi daha hızlı olabilir, çünkü tamamen donanımda hesaplanabilir.
Olası kopyaya da bir göz atın C ++ 'da bir tamsayı log2 () nasıl yapılır?
uint16_t log2(uint32_t n) {//but truncated
if (n==0) throw ...
uint16_t logValue = -1;
while (n) {//
logValue++;
n >>= 1;
}
return logValue;
}
Temelde tomlogic'inki ile aynı .
Math.h (C) veya cmath (C ++) eklemelisiniz Elbette bildiğimiz matematiği takip etmeniz gerektiğini unutmayın ... sadece> 0 sayıları.
Misal:
#include <iostream>
#include <cmath>
using namespace std;
int main(){
cout<<log2(number);
}
Sadece en önemli bitin konumunun ve kullandığım mikrodenetleyicinin matematik kitaplığı olmadığı için daha fazla hassasiyete ihtiyacım vardı. Pozitif tamsayı değer bağımsız değişkenleri için sadece 2 ^ n değerleri arasında doğrusal bir yaklaşım kullanmanın işe yaradığını buldum. İşte kod:
uint16_t approx_log_base_2_N_times_256(uint16_t n)
{
uint16_t msb_only = 0x8000;
uint16_t exp = 15;
if (n == 0)
return (-1);
while ((n & msb_only) == 0) {
msb_only >>= 1;
exp--;
}
return (((uint16_t)((((uint32_t) (n ^ msb_only)) << 8) / msb_only)) | (exp << 8));
}
Ana programımda, N * log2 (N) / 2 sonucunu bir tam sayı sonucuyla hesaplamam gerekiyordu:
temp = (((uint32_t) N) * yaklaşık_log_base_2_N_times_256) / 512;
ve 16 bit değerin tümü hiçbir zaman% 2'den fazla kapalı değildi
Yukarıdaki cevapların tümü doğrudur. Aşağıdaki cevabım, birinin ihtiyacı olursa yardımcı olabilir. Bu gereksinimi C kullanarak çözdüğümüz birçok soruda gördüm.
log2 (x) = logy (x) / logy (2)
Ancak, C dilini kullanıyorsanız ve sonucun tamsayı olmasını istiyorsanız, aşağıdakileri kullanabilirsiniz:
int result = (int)(floor(log(x) / log(2))) + 1;
Bu yardımcı olur umarım.
Ustaman Sangat'ın yaptığı şeyin geliştirilmiş versiyonu
static inline uint64_t
log2(uint64_t n)
{
uint64_t val;
for (val = 0; n > 1; val++, n >>= 1);
return val;
}