以下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 )
答案 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
旧版本。)