如何仅用Bazel特性模拟浮点类型并生成浮点数字符串?
如何仅用Bazel原生特性生成浮点数字符串(Bazel 0.26.0)
问题描述
我使用的Bazel版本是0.26.0,它不支持浮点类型。我希望计算一些“魔法”浮点数并将其存储为字符串,原本的逻辑用Python写是这样的:
def magicNumber(): fileStr = "" count = 200 for i in range(0, count-1): v = i / count fileStr += str(v) + " " return fileStr我不想依赖批处理/Shell脚本,只想用Bazel原生特性实现这个需求,请问有没有可行的实现思路?
解决方案
没问题,我刚好有个思路可以完全用Bazel的Starlark语言来实现这个需求——毕竟0.26.0的Starlark虽然不支持原生浮点,但我们可以用整数运算模拟出想要的浮点数字符串:
核心思路
i/count本质上是一个分数,我们可以通过整数运算把这个分数转换成对应的浮点格式字符串:
- 把分子
i放大足够倍数(比如针对count=200,放大1000倍就能保留三位小数的精度),得到小数部分的整数表示; - 把整数格式的小数部分转换成字符串,补零对齐位数;
- 拼接整数部分(这里都是0)和小数部分,再去掉末尾多余的零让结果更简洁;
- 最后把所有浮点数字符串用空格连接起来。
具体实现代码
你可以在.bzl文件或者BUILD文件里定义这个Starlark函数:
def magic_number(count = 200): result = [] for i in range(count - 1): # 用整数运算模拟浮点计算:i/count = (i * 1000) / count / 1000 decimal_int = (i * 1000) // count # 格式化三位小数,补零保证位数一致 decimal_str = "%03d" % decimal_int # 拼接成0.xxx格式的字符串 float_str = "0.%s" % decimal_str # 去掉末尾多余的零和可能的 trailing dot float_str = float_str.rstrip('0').rstrip('.') if '.' in float_str else float_str result.append(float_str) # 用空格连接所有结果 return " ".join(result)
如何使用这个函数
比如你想生成一个包含这些浮点数的文件,可以用genrule调用这个函数:
genrule( name = "generate_magic_numbers", outs = ["magic_numbers.txt"], cmd = "echo '$(call magic_number,200)' > $@", )
执行bazel build :generate_magic_numbers后,就能在bazel-bin目录下得到magic_numbers.txt文件,里面的内容和你用Python函数生成的完全一致。
注意事项
- 如果你的
count值发生变化,只需要调整放大的倍数(比如count=100时放大100倍即可),保证小数精度满足需求; - 这个实现完全依赖Bazel原生的Starlark特性,不需要任何外部脚本或工具,符合你的需求。
内容的提问来源于stack exchange,提问作者Vertexwahn
相关产品推荐
相关产品推荐

