Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
关于for循环和reduce的Python之谜_Python_Numpy_Lambda_Functional Programming - Fatal编程技术网

关于for循环和reduce的Python之谜

关于for循环和reduce的Python之谜,python,numpy,lambda,functional-programming,Python,Numpy,Lambda,Functional Programming,我试图计算一个可执行文件的字节熵。在得到直方图作为数组后,我首先使用for循环来计算它。然后我试着使用functools.reduce来稍微紧固一点。有趣的是,我从同一个数组和同一个函数中得到了不同的结果,我想知道为什么 我把它简化为一个简单的循环和两行代码块,但我不明白为什么其中一个是错误的。我比较了for循环中列表“prob”和“prob”的所有元素,所有值都是相同的 calc_entropy = lambda e,p: e - p*math.log(p,256) if (p != .0)

我试图计算一个可执行文件的字节熵。在得到直方图作为数组后,我首先使用for循环来计算它。然后我试着使用functools.reduce来稍微紧固一点。有趣的是,我从同一个数组和同一个函数中得到了不同的结果,我想知道为什么

我把它简化为一个简单的循环和两行代码块,但我不明白为什么其中一个是错误的。我比较了for循环中列表“prob”和“prob”的所有元素,所有值都是相同的

calc_entropy = lambda e,p: e - p*math.log(p,256) if (p != .0) else e

prob = hist / bytes_len
e = functools.reduce(calc_entropy, prob)


其中一个给出0.813826598594107,另一个给出0.8605594205272858。“hist”是一个名词

您的初始值不同。
在循环版本中,您首先应用
calc_熵(0,prob[0])
,但使用reduce时,您的第一个应用是
calc_熵(prob[0],prob[1])
。您可以通过调用带有初始值的
reduce
来改变这一点:
reduce(计算熵,prob,0)

正如@YSelf在回答中指出的那样,问题是初始值

下面是一个演示:

import functools
import math
import numpy as np

calc_entropy = lambda e, p: e - p*math.log(p, 256) if (p != .0) else e

def f1a(hist, bytes_len):
    prob = hist / bytes_len
    e = functools.reduce(calc_entropy, prob)              # no initial value
    return e


def f1b(hist, bytes_len):
    prob = hist / bytes_len
    e = functools.reduce(calc_entropy, prob, 0.0)         # with initial value
    return e


def f2(hist, bytes_len):
    e = 0.0
    for freq in hist:
        prob = freq / bytes_len
        e = calc_entropy(e, prob)
    return e
一些测试(我只展示了一个测试,但我做了几个不同数字的测试,所有测试的结论如下):


请注意
f1b()
f2()
的结果是如何相等的,但不同于
f1a()

如果您给出
hist
字节长度,我会很高兴。您可以将np.random与np.random.seed(123)一起使用。您的
numpy.ndarray历史记录中的
dtype
是什么?是浮点型还是整数型?我猜:
/
中的浮点精度是问题所在@阿列克西:这是个裸体。float64@FelixMartinez但是,循环中的所有“prob”值都等于数组中的相应值。这是有意义的。等待批准是的。你是对的-我做了一个只有3个元素的数组的实验,这似乎是一个可能的原因。我把我的实验也贴出来作为答案。
import functools
import math
import numpy as np

calc_entropy = lambda e, p: e - p*math.log(p, 256) if (p != .0) else e

def f1a(hist, bytes_len):
    prob = hist / bytes_len
    e = functools.reduce(calc_entropy, prob)              # no initial value
    return e


def f1b(hist, bytes_len):
    prob = hist / bytes_len
    e = functools.reduce(calc_entropy, prob, 0.0)         # with initial value
    return e


def f2(hist, bytes_len):
    e = 0.0
    for freq in hist:
        prob = freq / bytes_len
        e = calc_entropy(e, prob)
    return e
>>> b = 5
>>> h = np.random.rand(10)
>>> h
[0.68968912 0.37621079 0.76577699 0.06287911 0.49159805 0.63960027
 0.50323918 0.56442714 0.28445216 0.03391277]

>>> f1a(h, b)
0.4449530941371813
>>> f1b(h, b)
0.3562920060014537
>>> f2(h, b)
0.3562920060014537