Шеннон Энтропия

Следующий код C ++ (как есть) взят из http://rosettacode.org/wiki/Entropy. Есть ошибки — кто-нибудь может их исправить?

#include <string>
#include <map>
#include <iostream>
#include <algorithm>
#include <cmath>

double log2( double number ) {
return log( number ) / log( 2 ) ;
}

int main( int argc , char *argv[ ] ) {
std::string teststring( argv[ 1 ] ) ;
std::map<char , int> frequencies ;

for ( char c : teststring )
frequencies[ c ] ++ ;

int numlen = teststring.length( ) ;
double infocontent = 0 ;

for ( std::pair<char , int> p : frequencies ) {
double freq = static_cast<double>( p.second ) / numlen ;
infocontent += freq * log2( freq ) ;
}

infocontent *= -1 ;

std::cout << "The information content of " << teststring
<< " is " << infocontent << " !\n" ;
return 0 ;
}

Первая ошибка, кажется, исправлена ​​с помощью:

double log2( double n )
{
// log(n)/log(2) is log2.
return log( n ) / log( 2. );
}

Я не уверен, что они пытаются сказать:

for ( char c : teststring )

-1

Решение

Это одна хорошая работа

template <typename T> static float ShannonEntropy(T data[],int elements){
float entropy=0;
std::map<T,long> counts;
typename std::map<T,long>::iterator it;
//
for (int dataIndex = 0; dataIndex < elements; ++dataIndex) {
counts[data[dataIndex]]++;
}
//
it = counts.begin();
while(it != counts.end()){
float p_x = (float)it->second/elements;
if (p_x>0) entropy-=p_x*log(p_x)/log(2);
it++;
}
return entropy;
}
2

Другие решения

Цикл является циклом foreach. Это означает: для каждого символа в тестовой строке поместите его в переменную c и выполните тело цикла.

То же самое можно выразить обычным циклом for и индексной переменной, но этот способ намного короче и проще для чтения. Другие языки, такие как C # и Java, имели это долгое время, но в C ++ были только некоторые шаблонные функции в STL, которые были не так удобочитаемы.

Это новая особенность C++ 11 и ваш компилятор будет жаловаться, если он не совместим. Если вы получаете ошибки, попробуйте найти лучший компилятор.

1

Вот мой код Java для энтропии изображения

public static double getShannonEntropy_Image(BufferedImage actualImage){
List<String> values= new ArrayList<String>();
int n = 0;
Map<Integer, Integer> occ = new HashMap<>();
for(int i=0;i<actualImage.getHeight();i++){
for(int j=0;j<actualImage.getWidth();j++){
int pixel = actualImage.getRGB(j, i);
int alpha = (pixel >> 24) & 0xff;
int red = (pixel >> 16) & 0xff;
int green = (pixel >> 8) & 0xff;
int blue = (pixel) & 0xff;
//0.2989 * R + 0.5870 * G + 0.1140 * B greyscale conversion
//System.out.println("i="+i+" j="+j+" argb: " + alpha + ", " + red + ", " + green + ", " + blue);
int d= (int)Math.round(0.2989 * red + 0.5870 * green + 0.1140 * blue);
if(!values.contains(String.valueOf(d)))
values.add(String.valueOf(d));
if (occ.containsKey(d)) {
occ.put(d, occ.get(d) + 1);
} else {
occ.put(d, 1);
}
++n;
}
}
double e = 0.0;
for (Map.Entry<Integer, Integer> entry : occ.entrySet()) {
int cx = entry.getKey();
double p = (double) entry.getValue() / n;
e += p * log2(p);
}
return -e;
}
1

Первая ошибка из-за фиаско в отношении имен из библиотеки C. Не указано, какие перегрузки log сбрасываются в глобальное пространство имен; по-видимому, авторская реализация была только одна, так что log(2) однозначно, но у вас есть все из них, давая двусмысленность, так как нет того, который принимает тип int, Для мобильности это должно быть std::log(2.), Еще лучше, используйте std::log2 а не изобретать это заново.

Второе является «на основе диапазона for Statement «, введенный в язык в 2011 году, который выполняет итерацию по каждому элементу массива, контейнера или другой последовательности. Вам потребуется достаточно современный компилятор, и вам может потребоваться специально включить поддержку C ++ 11. Например, с GCC вам нужен аргумент командной строки -std=c++11 (или же c++0x с более старыми версиями).

0
По вопросам рекламы [email protected]