gnuplot 5.4 如何在坐标轴刻度标签中完整显示大整数?
使用 set format y "%.0f" 可以取消科学计数法,但大整数显示出来的末尾数字不一定与输入一致。如果需要逐位保留原始数字,可以将原始数据用作字符串标签;如果还要保留细小的数值间隔,应先用整数运算减去基准值,再交给 gnuplot 绘图。
只需要取消科学计数法
在原命令中设置格式即可:
for i in 1 2 3; do date +%s%N; done |
gnuplot --persist -e 'set format y "%.0f"; plot "-" with points'
%.0f 使用定点格式,不显示小数位。X 轴的对应设置是:
set format x "%.0f"
在数值刻度格式中,%s 有专门的尾数含义,并不表示“输出原始字符串”。gnuplot 按 gprintf 规则处理刻度格式,不能直接套用 C 的 %u、%lld。gnuplot 5.4 格式说明
为什么完整显示后仍可能出现错误的末尾数字
在通常使用 IEEE 754 binary64 的平台上,double 有 53 位有效二进制精度,能精确表示绝对值不超过 2^53 = 9007199254740992 的所有整数。超过这个范围后,部分相邻整数会转换成同一个浮点值。gnuplot 数值精度说明
示例中的纳秒时间戳约为 10^18。将它作为绘图坐标处理时,低位数字可能已经丢失。%.0f 只能打印当前数值,无法恢复原始输入。
gnuplot 5.4 支持平台允许的 64 位整数运算,但绘图坐标和自动刻度仍不能因此保证任意大整数的精度。gnuplot 5.4 功能说明
让标签逐位显示原始输入
使用 yticlabels(1),可以把第一列的原始文本直接用作 Y 轴刻度标签:
for i in 1 2 3; do date +%s%N; done |
gnuplot --persist -e 'plot "-" using 0:1:yticlabels(1) with points notitle'
其中,using 0:1 将数据记录序号作为 X 坐标,第一列作为 Y 坐标。yticlabels(1) 从第一列读取字符串标签,不需要把坐标值重新格式化为整数。X 轴可以使用对应的 xticlabels(...)。gnuplot 5.4 刻度标签说明
这种方法保留的是标签文字,点的位置仍受浮点精度限制。如果两个输入值转换后的坐标相同,标签仍可能重叠。它也只为数据点添加标签,不会让自动刻度获得额外精度。
同时保留原始标签和纳秒间隔
更可靠的做法是把数据拆成三个字段:记录序号、相对基准的整数差值和原始整数字符串。下面使用 Python 3 在输入 gnuplot 前完成整数减法。
先保存原始输入:
for i in 1 2 3; do date +%s%N; done > timestamps.txt
生成绘图数据:
python3 - <<'PY' > plot-data.txt
from pathlib import Path
values = Path('timestamps.txt').read_text().split()
if values:
base = int(values[0])
for index, original in enumerate(values):
delta = int(original) - base
print(index, delta, original)
PY
随后绘图:
gnuplot --persist -e 'set ylabel "Offset from first sample (ns)"; plot "plot-data.txt" using 1:2:yticlabels(3) with points notitle'
此时 Y 坐标是相对第一个样本的纳秒差值,标签显示完整的原始时间戳。只要差值的绝对值不超过 2^53,整数差值转换为常见的 binary64 坐标时就能保持精确。
应先做精确整数减法,再转换为绘图坐标。如果先把两个大整数转换为 double,再相减,已经丢失的低位数字就无法找回。数据较多时,应减少自定义标签的数量,避免长整数标签挤在一起。
备注:内容仅供参考。
