Lua 使用浮点或双精度代替整数

Lua 使用浮点或双精度代替整数,lua,floating-accuracy,Lua,Floating Accuracy,我知道Lua的默认实现只使用浮点数,因此避免了在选择要使用的数学函数变量之前动态确定数字的子类型的问题 我的问题是——如果我尝试在标准C99中将整数模拟为双精度(或浮点数),是否有可靠(且简单)的方法来准确地判断可表示的最大值是什么 我的意思是,如果我使用64位浮点来表示整数,我当然不能表示所有的64位整数(鸽子洞原理适用于这里)。我如何知道可表示的最大整数 (尝试列出所有值不是一个解决方案——例如,如果我在64位体系结构中使用double,因为我必须列出2^{64}个数字) 谢谢 对于64位双

我知道Lua的默认实现只使用浮点数,因此避免了在选择要使用的数学函数变量之前动态确定数字的子类型的问题

我的问题是——如果我尝试在标准C99中将整数模拟为双精度(或浮点数),是否有可靠(且简单)的方法来准确地判断可表示的最大值是什么

我的意思是,如果我使用64位浮点来表示整数,我当然不能表示所有的64位整数(鸽子洞原理适用于这里)。我如何知道可表示的最大整数

(尝试列出所有值不是一个解决方案——例如,如果我在64位体系结构中使用double,因为我必须列出2^{64}个数字)


谢谢

对于64位双精度浮点,可表示整数的最大值为253(9007199254740992),对于32位浮点,可表示整数的最大值为224(16777216)。请参阅上的基本数字

在Lua中验证这一点非常简单:

local maxdouble=2^53
--小于最大值的一个可以精确表示
打印(字符串格式(“%.0f”,maxdouble-1))-->9007199254740991
--最大值本身可以精确表示
打印(字符串格式(“%.0f”,maxdouble))-->9007199254740992
--超过最大值的一个将向下舍入
再次打印(string.format(“%.0f”,maxdouble+1))-->9007199254740992
如果我们手边没有IEEE定义的字段大小,知道我们对浮点数设计的了解,我们可以使用简单的循环在可能的值上确定这些值:

#包括
#包括
#包括
#定义最小值(a,b)(a
原始二进制值将通过转换为十进制值并再次使用以下方法保留:

  • 二进制数为5位十进制数字16
  • 二进制的9位十进制数字32
  • 17位十进制数字表示二进制64
  • 36位十进制数字表示二进制128

如果您正在查看int到float和返回int之间的转换,那么在我的系统上,它在16777217左右发生故障(double没有任何问题):

#包括
#包括
内部主(空)
{
久而久之;
双d;
浮动f;
对于(in=0;in<(LONG_MAX);in++){
d=英寸;
f=英寸;
out=d;
如果(输入!=输出){
printf(“对%ld\n的双转换不精确”,in);
}
out=f;
如果(输入!=输出){
printf(“对%ld\n的浮点转换不精确”,in);
}
}
返回0;
}

是的,但我想要一个连续范围的可精确表示的整数作为浮点数。例如,-2.0,-1.0,0.0,1.0,2.0可以被视为“精确”,但我不知道我能走多远。谢谢!这正是我需要的。我从主要答案中删掉了这个,因为它基本上是无关的,但双精度的最大可能值列在中-它比googol立方稍大。说2^53是“最大精确整数值”是不正确的。它是ma的最大值ntissa。例如,该数字的两倍的FP表示法没有不精确之处。但是,2^53是问题的正确答案,因为OP询问的是一个连续范围。我想我应该澄清一件事:我想要一个可以精确表示为浮点数(或双精度)的连续数字范围。其目的是放弃long、long和int,只使用浮点数(或double),但我需要知道我的“MAX_REPREENTABLE_INTEGER”是什么。Lua 5.3目前实际上设置为使用整数作为整数,除非将它们与浮点数混合或执行普通(非整数)运算除法。令人兴奋!这有两个问题:1.
long
的长度不足以表示
double
的所有整数值,即使它是
无符号的(
ULONG\u MAX
,2^32-1仍然小于2^53).2.即使您使用的是
无符号long-long
,按1数到2^53也需要大约18天的时间(我的计算机将计算到2^29并将其乘以2^24)。查看我的解决方案,了解更实用的循环。很好的解决方案。即使考虑IEEE浮点表示法,我也无法说服自己它不会在功率转换之间的某个地方崩溃,尽管我越想它就越明显。很好地理解了
long
没有覆盖问题。这是十进制字符串转换,而不是内部表示。
#include <stdio.h>
#include <limits.h>

int main (void)
{
  long in, out;
  double d;
  float f;

  for (in=0; in < (LONG_MAX); in++) {
    d=in;
    f=in;
    out=d;
    if (in != out) {
      printf ("Double conversion imprecise for %ld\n", in);
    }
    out=f;
    if (in != out) {
      printf ("Float conversion imprecise for %ld\n", in);
    }
  }
  return 0;
}