如何在没有外部库的任何lua中将双精度转换为小字符串表示而不会丢失数据?

Posted

技术标签:

【中文标题】如何在没有外部库的任何lua中将双精度转换为小字符串表示而不会丢失数据?【英文标题】:How to convert a double to a small string representation without data loss in any lua without external libs? 【发布时间】:2018-07-07 10:56:19 【问题描述】:

我想仅使用任何 Lua 版本将数字转换为字符串,以便

没有数据丢失(必要!)

字符串表示尽可能小(8 字节就可以)(可选,不是必需的)

没有使用外部库(必需!)

转换速度尽可能快(可选,非必需)

我不在乎

人类可读性 避免特殊字符

我尝试了内置的tonumber 函数,但它并不总是给出正确的结果:

> print((2+256^6)==(1+256^6))
false
> print(tostring(2+256^6)==tostring(1+256^6))
true

【问题讨论】:

根据定义,浮点数是有损的 - 如果您确实需要避免 任何 数据丢失,则不能一开始就使用浮点数。 lua 有一种数字数据类型 - 这些数字是双精度数 - 我希望能够序列化这些数据,以便能够序列化除用户数据和线程之外的任何内容... 有人可以发布完整的解决方案吗? SO 不是给出完整解决方案的地方 你从哪里得到的?我看到了许多像我这样的小问题的完整解决方案!我不认为序列化一个数字是一门大科学。此外,如果只有错误的答案,将它们嵌入程序的人会遇到严重的问题!他们尝试序列化一个 nan,想知道为什么在反序列化数据时会得到 nil! 【参考方案1】:

如果您可以使用标准 Lua 库,请尝试以下方法:

x=math.pi

s=string.pack("d",x)
y=string.unpack("d",s)
print(x==y)

s=string.format("%a",x)
y=tonumber(s)
print(x==y)

string.format("%a",x) 在 Lua 5.2+ 中可用。 string.pack 在 Lua 5.3+ 中可用。

【讨论】:

似乎比 tostring 好!如何反序列化?任何lua版本都有string.format吗? 试过了:你不能使用 tonumber 反序列化 (-)nans 和 (-)infs,但其他任何一个都可以。 另外(lua-users.org/wiki/StringLibraryTutorial 关于 string.format)“选项 A, a 可能在 Lua 5.2 及更高版本中可用。” (它应该适用于任何 lua 版本),string.pack 根本不在我的 lua 中。 "string.format("%a",x) 在 Lua 5.2+ 中可用。string.pack 在 Lua 5.3+ 中可用。" - 没有解决问题。还支持 nans、infs 及其否定版本。【参考方案2】:
   -- Encoding/decoding without data loss

   local NaN_serialized = 
      [string.format('%.17g',   1/0 )] =  '1/0',
      [string.format('%.17g',  -1/0 )] = '-1/0',
      [string.format('%.17g',   0/0 )] =  '0/0',
      [string.format('%.17g', -(0/0))] =  '-(0/0)'
   
   -- How to encode:
   str_value = string.format('%.17g', num_value):gsub('^.*', NaN_serialized):gsub(',', '.')

   -- How_to_decode:
   num_value = loadstring("return "..str_value)()

【讨论】:

似乎可以工作(至少在我目前使用的 lua 上)。 pro:非常非常短的解决方案,kontra:字符串表示非常大。【参考方案3】:

这包括一个 number_to_str 和一个 number_from_str 函数:

https://github.com/bakpakin/binser/blob/master/binser.lua

显然,它们的能力超过了 Lua 的内置 tonumber...

【讨论】:

print(number_from_str(number_to_str(-(0/0)),1) == -(0/0)) 给出错误。这并没有保存 nan 和 -nan 之间的区别,而且,这是相当多的代码。如果你将它分叉并制作一个可以工作的版本,那就没问题了。 如果不处理NaN,你可以自己轻松添加。 是的,但我不想检查代码页是否有进一步的错误,如果你这样做了,但你没有发现你的解决方案是好的。 我没有时间这样做 至于你的(-0/0)==(-0/0) 测试,没有“minus nan”***.com/a/37759548/4687565

以上是关于如何在没有外部库的任何lua中将双精度转换为小字符串表示而不会丢失数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何在R中将两个变量(整数)转换为双精度?

如何在 PySpark 1.6 中将 DataFrame 列从字符串转换为浮点/双精度?

如何使用 stringstream 在 C++ 中将字符串转换为双精度值 [关闭]

如何在 C++ 中将字符串转换为双精度值?

如何在 .NET 中将双精度值转换为具有固定小数位数的小数类型值

尝试在 C++ 中将字符串转换为双精度时遇到分段错误