我喜欢为VS.NET和GCC免费提供代码警告,我喜欢让我的代码准备好64位.
今天我写了一个小模块来处理内存缓冲区,并通过文件样式的接口提供对数据的访问(例如,你可以读取字节,写字节,搜索等).
作为当前读取位置和大小的数据类型,我使用size_t,因为这似乎是最自然的选择.我绕过警告,它也应该在64位工作.
以防万一:我的结构看起来像这样:
typedef struct
{
unsigned char * m_Data;
size_t m_CurrentReadPosition;
size_t m_DataSize;
} MyMemoryFile;
Run Code Online (Sandbox Code Playgroud)
签名size_t似乎没有在实践中定义.Google代码搜索证明了这一点.
现在我处于两难境地:我想检查增加size_t的溢出因为我必须处理用户提供的数据,第三方库将使用我的代码.但是,对于溢出检查,我必须知道符号.它在实施中产生了巨大的差异.
那么 - 我应该如何在平台和编译器独立的方式编写这样的代码?
我可以检查size_t运行或编译时的签名吗?这将解决我的问题.或者也许size_t首先不是最好的主意.
有任何想法吗?
编辑:我正在寻找C语言的解决方案!
我们有一些整数算术,由于历史原因,它必须在PHP上使用与在一些静态类型语言中相同的算法.自从我们上次升级PHP以来,溢出整数的行为已经改变.基本上我们使用以下公式:
function f($x1, $x2, $x3, $x4)
{
return (($x1 + $x2) ^ $x3) + $x4;
}
Run Code Online (Sandbox Code Playgroud)
但是,即使有转换:
function f($x1, $x2, $x3, $x4)
{
return intval(intval(intval($x1 + $x2) ^ $x3) + $x4);
}
Run Code Online (Sandbox Code Playgroud)
我仍然以完全错误的数字结束......
例如,使用$ x1 = -1580033017,$ x2 = -2072974554,$ x3 = -1170476976)和$ x4 = -1007518822,我最终得到PHP中的-30512150和C#中的1617621783.
只是加在一起$ x1和$ x2我无法得到正确的答案:
在C#我得到
(-1580033017 + -2072974554) = 641959725
Run Code Online (Sandbox Code Playgroud)
在PHP中:
intval(intval(-1580033017) + intval(-2072974554)) = -2147483648
Run Code Online (Sandbox Code Playgroud)
这与:
intval(-1580033017 + -2072974554) = -2147483648
Run Code Online (Sandbox Code Playgroud)
我不介意写一个"IntegerOverflowAdd"函数或其他东西,但我不太清楚如何(-1580033017 + -2072974554)等于641959725.(我确实认为它是-2147483648 +(2*2 ^ 31) ,但是-2147483648 + 2 ^ 31是-1505523923,它大于Int.Min那你为什么要加2*2 ^ 31而不是2 …
我写了一个方法来将给定数字从天转换为毫秒:
private long expireTimeInMilliseconds;
...
public void setExpireTimeInDays(int expireTimeInDays)
{
expireTimeInMilliseconds = expireTimeInDays * 24 * 60 * 60 * 1000;
}
Run Code Online (Sandbox Code Playgroud)
我很难弄明白我做错了什么.现在我的问题是: 这个错误是如此明显吗?
纠正方法:
private long expireTimeInMilliseconds;
...
public void setExpireTimeInDays(int expireTimeInDays)
{
expireTimeInMilliseconds = ((long) expireTimeInDays) * 24 * 60 * 60 * 1000;
}
Run Code Online (Sandbox Code Playgroud)
如果我在计算之前没有将整数转换为long,那么我得到一个完全错误的结果.
我只是学习在Clojure中使用延迟序列,我不确定我在下面的代码中做错了什么:
(defn sum [seqn]
(reduce + seqn))
(defn fib
([] (concat [0 1] (fib 0 1)))
([a b] (lazy-seq (cons (+ a b) (fib b (+ a b))))))
(defn up-to [n seqn]
(filter (fn [x] (< x n)) seqn))
(sum (up-to 100 (fib))) => ArithmeticException integer overflow clojure.lang.Numbers.throwIntOverflow (Numbers.java:1388)
Run Code Online (Sandbox Code Playgroud)
求和的数字不应大于100,那导致整数溢出的原因是什么?
在较长的脚本中,我必须将向量A(2614)的长度乘以数据帧B(1456000)的行数.如果我直接这样做,length(A) * nrow(B)我会得到消息,NAs produced by integer overflow虽然当我乘以相同的数字时没有问题:
2614 * 1456000
[1] 3805984000
Run Code Online (Sandbox Code Playgroud)
使乘法运算的唯一方法是round(length(A)) * nrow(B)或length(A) * round(nrow(B)).但这些数字所生产length和nrow必须为整数无论如何!此外,我使用函数is.integer的帮助页面上建议的以下函数对此进行了测试...
is.wholenumber <- function(x, tol = .Machine$double.eps^0.5) abs(x-round(x)) < tol
Run Code Online (Sandbox Code Playgroud)
......当然,他们是整数.那么为什么我需要拐杖"圆"呢?非常令人费解......有人知道背景中发生了什么?
在C编程中,我发现了一个奇怪的问题,这反驳了我的直觉.当我声明a integer为INT_MAX(2147483647在limits.h中定义)并将其隐式转换为float值时,它工作正常,即浮点值与最大整数相同.然后,我将浮动转换回整数,发生了一些有趣的事情.new integer成为最小整数(-2147483648).
源代码如下所示:
int a = INT_MAX;
float b = a; // b is correct
int a_new = b; // a_new becomes INT_MIN
Run Code Online (Sandbox Code Playgroud)
我不确定浮点数b转换为整数时会发生什么a_new.那么,有没有合理的解决方案来找到可以在其间切换的最大值integer和float类型?
PS:INT_MAX- 100 的值工作正常,但这只是一个随意的解决方法.
问题动机:
在我所知道的标准数值语言中(例如Matlab,Python numpy等),例如,如果你取一个适度大数的指数,那么输出就是数值溢出的结果.如果将此值乘以0,则得到NaN.另外,这些步骤足够合理,但它们揭示了数学实现中的逻辑错误.由溢出产生的第一个数已知是有限的,我们显然希望乘以0的结果,这个大的有限数为0.
明确:
>>> import numpy as np
>>> np.exp(709)*0
0.0
>>> np.exp(710)*0
nan
Run Code Online (Sandbox Code Playgroud)
我想我们可以在这里引入一个"最大有限值"(LFV)的概念,它具有以下特性:
另一方面,不应简单地以对LFV描述的方式重新定义无穷大.对于0*infinity = 0没有意义......恰当地,无穷大的当前标准实现在此设置中产生NaN.此外,有时需要将数字初始化为无穷大,并且您需要任何数值运算的结果,即使产生LFV的结果严格小于初始化值(这对某些逻辑语句也很方便).我敢肯定,其他情况存在,其中一个适当的无限是必要的-我的观点很简单,就是无穷大应该不会简单地被重新定义为具有上面的一些LFV属性.
问题:
我想知道是否有任何语言使用这样的方案,如果这样的方案有任何问题.在正确的数学中不会出现这个问题,因为对数字的大小没有这些数值限制,但我认为在编程语言中实现一致的数学时这是一个真正的问题.基本上,通过LFV,我想我想要最大显式值和无穷大LFV =(LEV,无穷大)之间的开放间隔的简写,但也许这种直觉是错误的.
更新:在评论中,人们似乎反对我提出的问题的实用性.我的问题不是因为发生了许多相关问题,而是因为在许多不同的环境中经常出现同样的问题.通过与进行数据分析的人交谈,这在训练/拟合模型时经常足以导致运行时错误.问题基本上是为什么这不是由数字语言处理的.从评论中,我基本上认为编写语言的人看不到以这种方式处理事物的效用.在我看来,当某些特定问题经常发生在使用某种语言的人身上时,以原则方式处理这些异常可能是有意义的,因此每个用户都不必这样做.
我有以下示例代码:
UInt16 a = 0x3A;
UInt16 b = 0xFFDF;
UInt16 result = Convert.ToUInt16(a - b);
Run Code Online (Sandbox Code Playgroud)
带有溢出异常的第3行错误.但是我希望得到相同的结果,就像我在C中减去2个无符号短路并且它们上/下溢.
实现这一目标的最恰当方法是什么?
这个可能很容易.我们知道运算符&+对整数(环绕)进行模运算,而运算符+会导致错误.
$ swift
1> var x: Int8 = 100
x: Int8 = 100
2> x &+ x
$R0: Int8 = -56
3> x + x
Execution interrupted. Enter Swift code to recover and continue.
Run Code Online (Sandbox Code Playgroud)
这有什么错误?我无法抓住它,我无法将其转为可选:
4> do {try x + x} catch {print("got it")}
Execution interrupted. Enter Swift code to recover and continue.
5> try? x + x
Execution interrupted. Enter Swift code to recover and continue.
Run Code Online (Sandbox Code Playgroud)
我很确定这种错误是这个StackOverflow问题(除零)的错误,但我不知道是否可以捕获这种错误.我错过了什么简单的事情?可以被困吗?如果是这样,怎么样?
蟒2具有两个整数数据类型int和long,并自动将它们之间作为转换必要,特别是为了避免整数溢出.
我在Python中模拟C函数,我想知道是否有重新启用整数溢出的标准方法.对于nonce,我已经习惯了
overflow_point = maxint + 1
if value > overflow_point:
value -= 2 * overflow_point
Run Code Online (Sandbox Code Playgroud)
是否有更标准的方法来做同样的事情?