研发7年,目前年包80左右。是外企继续苟着还是回老家国企?
刚看到个贴子,说一位34岁的研发,干了7年,年包80万,现在纠结要不要回老家国企,月薪7k,正式合同但无编制。说实话,这问题戳中了很多打工人的痛点。
我觉得吧,这不是简单的“钱多还是钱少”的选择,而是“你想过什么样的生活”。外企80万听着香,但焦虑、加班、随时被优化;回国企虽然稳,却得接受节奏慢、收入差距大的落差。网友有说“国企养老”,也有人说“回去就是废掉”,但我更认同:人得明白自己要什么。
如果真是累了想躺平,那就别怕低工资,能换来心安;可要是心里还不甘平庸,那就继续卷几年,把底子打厚。生活没有绝对轻松的路,关键是选自己能扛得住的那条。【备注:文末可领最新资料】
面试题:按权重随机选择
昨天晚上十一点多,在公司楼下抽烟…不对我不抽烟,反正就楼下吹风的时候,小李问我“按权重随机怎么写,random那个啥…choices?”我说有,但你别全信,咱把底层思路捋一遍,写两种版本,心里才踏实。就是那个…嗯,按权重抽签,权重大的人被抽到的概率更大,对吧。
先说最顺手的思路:把权重累加成一条“尺子”,随便在0到总长之间戳一下,落在哪段就选谁。这个靠谱,直观,也好调试。注意两点,一个是权重可能是浮点数,别强行转整;另一个是全是0就完蛋了,要提前校验。代码我用 bisect,二分查找定位区间,复杂度 O(log n),日常够用了。
import random
import bisect
from typing import List, Tuple, Any
defweighted_choice(items: List[Tuple[Any, float]]):
# items: [(对象, 权重)]
weights = [w for _, w in items]
if any(w < 0for w in weights):
raise ValueError("权重不能是负数")
total = sum(weights)
if total <= 0:
raise ValueError("总权重必须>0")
# 前缀和
prefix = []
s = 0.0
for w in weights:
s += w
prefix.append(s)
r = random.random() * total
idx = bisect.bisect_left(prefix, r)
return items[idx][0]
# 小测一把
if __name__ == "__main__":
items = [("A", 1), ("B", 3), ("C", 6)]
counts = {"A":0,"B":0,"C":0}
for _ in range(10000):
counts[weighted_choice(items)] += 1
print(counts)
刚打到这儿,手机响了…等等我接个电话…好了继续。上面那套在 n 很大、抽很多次的时候,其实构建一次前缀和,然后每次 O(log n)。要是你要在热路径里怼上百万次,还是想要“近似 O(1)”的感觉,那就上别名法(Alias Method),准备期 O(n),采样期 O(1)。思想是把每个格子都“填满”成平均概率,矮的借高的的剩余,采样时先选格子再抛一次硬币。实现别怕,几十行。
classAliasSampler:
def__init__(self, weights: List[float]):
if any(w < 0for w in weights):
raise ValueError("权重不能是负数")
total = sum(weights)
if total <= 0:
raise ValueError("总权重必须>0")
n = len(weights)
probs = [w * n / total for w in weights]
self.alias = [0]*n
self.prob = [0.0]*n
small, large = [], []
for i, p in enumerate(probs):
(small if p < 1.0else large).append(i)
while small and large:
s = small.pop()
l = large.pop()
self.prob[s] = probs[s]
self.alias[s] = l
probs[l] = probs[l] - (1.0 - probs[s])
(small if probs[l] < 1.0else large).append(l)
# 收尾
for i in large + small:
self.prob[i] = 1.0
self.alias[i] = i
defsample(self) -> int:
i = random.randrange(len(self.prob))
return i if random.random() < self.prob[i] else self.alias[i]
# 用法
if __name__ == "__main__":
items = ["A","B","C"]
sampler = AliasSampler([1,3,6])
from collections import Counter
c = Counter(items[sampler.sample()] for _ in range(10000))
print(c)
有人问细节对吧:权重特别大怎么办?别紧张,前缀和用 float,或者先把权重归一化(除以总和),但要注意累计误差,比较时尽量用二分别直接等值;另外“按权重不放回抽多个”的场景,简单暴力的是每次把被抽到的权重设为0再来一发,如果次数接近 n,干脆用洗牌+加权重排个序(Gumbel trick 也行,不过这就…算了不展开)。我现在有点困,回头把那个性能对比图再贴,你们先把这俩函数抄到工具库里,够用了。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html
虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB,点击下方公众号回复关键字 python 全部免费领