考虑以下示例。有一个图像,用户可以选择矩形区域(部分)。图像以某种比例显示。然后我们改变比例,我们需要重新计算选择的新坐标。我们拿宽度,
newSelectionWidth = round(oldSelectionWidth / oldScale * newScale)
其中oldScale = oldDisplayImageWidth / realImageWidth
,newScale = newDisplayImageWidth / realImageWidth
,除了比例之外的所有值都是整数。
问题如何证明newSelectionWidth = newDisplayImageWidth
对oldSelectionWidth = oldDisplayImageWidth
,oldDisplayImageWidth
,newDisplayImageWidth
的任何值realImageWidth
给出{{1}}?或者在什么条件下这不成立?
我正在考虑答案,这是我提出的,可能不准确和/或不完整。
JavaScript中的所有数字都是双精度数字。通常,这给出了大约10 -16 (machine epsilon)的最大误差。这意味着为了使误差为0.5或更大,(1)我们需要执行0.5 / 10 -16 = 5·10 15 操作。另一个错误来源是计算太大(|值|> 1.7976931348623157·10 308 )或数字太低(| value |< 2.2250738585072014·10 -308 )(link)。这意味着(2)如果在计算过程中某处我们的数字太大或太低,例如因为oldDisplayImageWidth / realImageWidth> 1.7976931348623157·10 308 等,则误差可能超过0.5。当然,我们谈论的是在今天的显示器上显示图像,所有这些情况都极不可能。
答案 0 :(得分:1)
你混淆了绝对和相对错误。假设相对误差为10 ^ -16,则在示例中的4个操作之后,最终的最大相对误差为4 * 10 ^ -16。你想要一个绝对错误&lt; 0.5,所以你很好,只要newSelectionWidth * 4 * 10^-16 < 0.5
。
答案 1 :(得分:1)
如果newDisplayWidth小于1125899906842624且其他整数为正且不超过53位,则newSelectionWidth
等于newDisplayWidth
。证据如下。
符号:
double
来命名所使用的浮点类型,IEEE-754 64位二进制文件。code
样式中的文本表示计算值,而纯文本表示数学值。因此,1/3恰好是三分之一,而1./3.
是在浮点运算中将1除以3的结果。我假设:
double
有效数字(53位)。oldDisplayImageWidth / realImageWidth
和newDisplayImageWidth / realImageWidth
在double
算术中执行,操作数转换为double
。对整数的限制可确保转换为double
是准确的,并且在此问题中使用的操作期间不会遇到溢出和下溢。
考虑oldScale
,double
设置为oldDisplayImageWidth / realImageWidth
。在舍入到最接近模式下的单个浮点运算中的最大误差是ULP的一半(因为每个数学数字不超过来自可表示数字的ULP的一半)。因此,oldScale
等于oldDisplayImageWidth / realImageWidth•(1 + e 0 ),其中e 0 表示相对误差,最多为{{1}的一半ε。 (double
epsilon是2 -52 ,所以| e 0 |≤2 -53 。)
同样,double
是newDisplayImageWidth / realImageWidth•(1 + e 1 ),其中e 1 是一个最多2个的错误-53
然后newScale
是oldSelectionWidth / oldSelectionWidth / oldScale
•(1 + e 2 ),再次针对某些e 2 ≤2 - 53 ,oldScale
是oldSelectionWidth / oldSelectionWidth / oldScale * newScale
•(1 + e 2 )•oldScale
•(1 + oldSelectionWidth / {{1} }(1 + e 3 )。请注意,这是传递给newScale
的参数。
现在替换我们对oldScale
和round
的表达式。这会产生oldSelectionWidth /(oldDisplayImageWidth / realImageWidth•(1 + e 0 ))•(1 + e 2 )•(newDisplayImageWidth / realImageWidth•(1 + e 1 ))•(1 + e 3 )。 realImageWidth术语取消,我们可以重新排列其他术语以生成oldSelectionWidth•newDisplayImageWidth / oldDisplayImageWidth•(1 + e 1 )•(1 + e 2 )•(1+ e 3 )/(1 + e 0 )。
我们得到oldSelectionWidth等于oldDisplayImageWidth,所以那些取消,oldScale
的参数正好是:newDisplayImageWidth•(1 + e 1 )•(1 + e 2 )•(1 + e 3 )/(1 + e 0 )。
考虑组合误差项减一(这是最终值中的相对误差):( 1 + e 1 )•(1 + e 2 )• (1 + e 3 )/(1 + e 0 ) - 1.当e 0 为-2 -53 ,其他为+2 -53 。然后它略大于2 ULP(至多324518553658426753804753784799233/730750818665451377972204001751459814038961127424)。如果newDisplayImageWidth小于1125899906842624,则newDisplayImageWidth乘以此相对误差小于½。因此,newDisplayImageWidth•(1 + e 1 )•(1 + e 2 )•(1 + e 3 )/(1 + e 0 )将在newDisplayImageWidth的½之内。
由于newDisplayImageWidth是一个整数,如果newScale
的参数在newDisplayWidth的½之内,那么结果就是newDisplayWidth。
因此,如果newDisplayWidth小于1125899906842624,则round
等于round
。
(以上证明1125899906842624是一个足够的限制,但可能没有必要。更复杂的分析可能能够证明某些错误组合是不可能的,因此最大组合误差小于上面使用的。放宽限制,允许更大的newDisplayWidth值。)