香农熵

时间:2014-01-07 07:12:50

标签: c++ entropy

以下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 )

4 个答案:

答案 0 :(得分:3)

这个很好用

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;
}

答案 1 :(得分:1)

循环是一个foreach循环。它意味着:对于teststring中的每个字符,将其放入变量c并执行循环体。

同样可以用常规for循环和索引变量表示,但这种方式更短,更容易阅读。像C#和Java这样的其他语言已经有很长一段时间了,但是C ++在STL中只有一些不可读的模板功能。

这是C++ 11的新功能,如果它不兼容,您的编译器会抱怨。如果出现错误,请尝试使用更好的编译器。

答案 2 :(得分: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;
}

答案 3 :(得分:0)

第一个错误是因为有关C库名称的惨败。没有指定将log的哪些重载转储到全局命名空间中;据推测,作者的实现只有一个,所以log(2)是明确的,但你的所有这些都是明确的,因为没有一个类型int。为了便于携带,它应该是std::log(2.)。更好的是,使用std::log2而不是重新发明它。

第二个是“基于范围的for语句”,在2011年引入该语言,它迭代数组,容器或其他序列的每个元素。您需要一个相当现代的编译器,您可能需要专门启用C ++ 11支持。例如,对于GCC,您需要命令行参数-std=c++11(或c++0x旧版本。)