- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
是否有一种简单的方法来判断特定数字是否在其浮点表示中进行四舍五入?我问的原因和我问的一个问题有关here并提出了类似的问题here , 在其他人中。
回顾一下,我试图问为什么,例如,表达式 0.5 % 0.1 不会导致大约为零,而是给出(大约)0.1。许多受访者喋喋不休地谈论大多数数字如何无法精确表示等等,但未能真正解释为什么对于某些值,当没有余数时,% 运算符的结果与零相差甚远。我花了很长时间才弄清楚发生了什么,我认为值得分享。另外,它解释了我为什么问我的问题。
如果除数以浮点格式向上舍入,但被除数却不是,则 % 运算符的结果似乎不会为零。除法算法迭代地从被除数中减去除数,直到得到负值。商是迭代次数,余数是被除数剩下的部分。可能不太清楚为什么这会导致错误(当然不是我),所以我将举一个例子。
对于 0.5 % 0.1 =(大约)0.1 的情况,0.5 可以精确表示,但 0.1 不能并且向上舍入。在二进制中,0.5 简单地表示为 0.1,但二进制中的 0.1 是 0.00011001100...重复最后 4 位数字。由于浮点格式的工作方式,在最初的 1 之后,它会被截断为 23 位(单精度)。(有关完整解释,请参阅被广泛引用的 What Every Computer Scientist Should Know About Floating-Point Arithmetic。)然后将其向上舍入,因为这更接近 0.1(十进制)值。因此,除法算法使用的值是:
0.1 0000 0000 0000 0000 0000 000 --> 0.5(十进制),并且
0.0001 1001 1001 1001 1001 1001 101 --> 0.1(十进制)
除法算法迭代次数为;
(1) 1.00000000000000000000000 - 0.000110011001100110011001101 =
(2) 0.011001100110011001100110011 - 0.000110011001100110011001101 =
(3) 0.01001100110011001100110011 - 0.000110011001100110011001101 =
(4) 0.001100110011001100110011001 - 0.000110011001100110011001101 =
(x)0.0001100110011001100110011 - 0.000110011001100110011001101 =
-0.000000000000000000000000001
如图所示,在第 4 次迭代之后,进一步相减将得到负数,因此算法停止,剩下的被除数值(以粗体显示)是余数,即小数 0.1 的近似值。
此外,表达式 0.6 % 0.1 可以按预期工作,因为 0.6 会向上舍入。表达式 0.7 % 0.1 无法按预期工作,尽管无法准确表示 0.7,但它不会向上舍入。我还没有对此进行详尽的测试,但我认为这就是正在发生的事情。这让我(终于!)想到了我的实际问题:
有谁知道判断特定数字是否会被四舍五入的简单方法?
最佳答案
让我们考虑 float a > b > 0
时的情况。每个 float 都是其 ulp 的倍数,我们可以这样写:
a = na*ulp(a). ulp(a)=2^ea
。 na 是 a 的整数有效数。 ea 是它的偏置指数。
b = nb*ulp(b). ulp(b)=2^eb
。 nb 是 b 的整数有效数。 eb 是其有偏指数。
对于标准化 float ,2^p > na >= 2^(p-1)
其中 p 是浮点精度(对于 IEEE 754 double ,p=53 位)。
因此我们可以执行(可能很大的)整数除法:na*2^(ea-eb)=nb*q+nr
从中我们推导出na*2^(ea-eb)*2^eb = nb*2^eb*q+nr*2^eb
,即a=b*q+nr*2^eb
.
换句话说,在标准化之前,nr 是浮点余数的整数有效数,eb 是其偏置指数。
由此可见,余数运算是精确的,因为显然nr <= nb,所以余数可以表示为float。因此严格来说,余数永远不会四舍五入。
当商四舍五入到最接近的整数而不是截断时,这是 IEEE 余数运算,
a=b*q+r
那么余数可以为负 r<0
在这种情况下,您感兴趣的是:
a=b*(q-1) + (b+r)
我认为这种情况下 r 为负,迫使 b+r
结果就是你所说的四舍五入。不幸的是,没有简单的方法可以在不执行该操作的情况下判断余数是否为负,除非 nb 是 2 的幂(在逐渐下溢的情况下为 2^(p-1) 或更小)。
但您似乎对具体案例感兴趣a=i/10^j
和b=1/10^j
但只有 float 近似float(i/10^j)
和float(1/10^j)
。假设 10^j 和 i 可以精确表示( double 下 j<23 且 i<=2^53),那么我们可以使用融合乘法加法来获取表示误差:
ea=fma(10^j,float(i/10^j),-i). 10^j*float(a)=10^j*a+ea.
eb=fma(10^j,float(1/10^j),-1). 10^j*float(b)=10^j*b+eb.
您有i*b=a
现在您想要比较它与浮点近似的情况,这样您就可以得到余数:
r = (a+ea/10^j)-i*(b+eb/10^j) = 1/10^j * ea - i/10^j * eb.
浮点近似可能有效,但并非总是有效:
float(float(float(b)*ea) - float(float(a)*eb))
但是,您最好再次使用 fma:
r = fma(-i,eb,ea)/10^j
余数的符号将为您提供浮点近似值的边...
这里我们稍微简化了问题,因为我们没有考虑商可能偏差超过 1 的情况。那应该没问题,因为 i < 2^53 但我们没有证明它。
这只是一种风格练习,因为我们正在用更复杂的表达式替换简单的表达式。
关于java - 如何知道以浮点格式表示时分数是否会向上舍入(re : java remainder [%] results when using fp's),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40061900/
我有一个 if 语句,如下所示 if (not(fullpath.lower().endswith(".pdf")) or not (fullpath.lower().endswith(tup
然而,在 PHP 中,可以: only appears if $foo is true. only appears if $foo is false. 在 Javascript 中,能否在一个脚
XML有很多好处。它既是机器可读的,也是人类可读的,它具有标准化的格式,并且用途广泛。 它也有一些缺点。它是冗长的,不是传输大量数据的非常有效的方法。 XML最有用的方面之一是模式语言。使用模式,您可
由于长期使用 SQL2000,我并没有真正深入了解公用表表达式。 我给出的答案here (#4025380)和 here (#4018793)违背了潮流,因为他们没有使用 CTE。 我很欣赏它们对于递
我有一个应用程序: void deleteObj(id){ MyObj obj = getObjById(id); if (obj == null) { throw n
我的代码如下。可能我以类似的方式多次使用它,即简单地说,我正在以这种方式管理 session 和事务: List users= null; try{ sess
在开发J2EE Web应用程序时,我通常会按以下方式组织我的包结构 com.jameselsey.. 控制器-控制器/操作转到此处 服务-事务服务类,由控制器调用 域-应用程序使用的我的域类/对象 D
这更多是出于好奇而不是任何重要问题,但我只是想知道 memmove 中的以下片段文档: Copying takes place as if an intermediate buffer were us
路径压缩涉及将根指定为路径上每个节点的新父节点——这可能会降低根的等级,并可能降低路径上所有节点的等级。有办法解决这个问题吗?有必要处理这个吗?或者,也许可以将等级视为树高的上限而不是确切的高度? 谢
我有两个类,A 和 B。A 是 B 的父类,我有一个函数接收指向 A 类型类的指针,检查它是否也是 B 类型,如果是将调用另一个函数,该函数接受一个指向类型 B 的类的指针。当函数调用另一个函数时,我
有没有办法让 valgrind 使用多个处理器? 我正在使用 valgrind 的 callgrind 进行一些瓶颈分析,并注意到我的应用程序中的资源使用行为与在 valgrind/callgrind
假设我们要使用 ReaderT [(a,b)]超过 Maybe monad,然后我们想在列表中进行查找。 现在,一个简单且不常见的方法是: 第一种可能性 find a = ReaderT (looku
我的代码似乎有问题。我需要说的是: if ( $('html').attr('lang').val() == 'fr-FR' ) { // do this } else { // do
根据this文章(2018 年 4 月)AKS 在可用性集中运行时能够跨故障域智能放置 Pod,但尚不考虑更新域。很快就会使用更新域将 Pod 放入 AKS 中吗? 最佳答案 当您设置集群时,它已经自
course | section | type comart2 : bsit201 : lec comart2 :
我正在开发自己的 SDK,而这又依赖于某些第 3 方 SDK。例如 - OkHttp。 我应该将 OkHttp 添加到我的 build.gradle 中,还是让我的 SDK 用户包含它?在这种情况下,
随着 Rust 越来越充实,我对它的兴趣开始激起。我喜欢它支持代数数据类型,尤其是那些匹配的事实,但是对其他功能习语有什么想法吗? 例如标准库中是否有标准过滤器/映射/归约函数的集合,更重要的是,您能
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 9 年前。 Improve
我一直在研究 PHP 中的对象。我见过的所有示例甚至在它们自己的对象上都使用了对象构造函数。 PHP 会强制您这样做吗?如果是,为什么? 例如: firstname = $firstname;
...比关联数组? 关联数组会占用更多内存吗? $arr = array(1, 1, 1); $arr[10] = 1; $arr[] = 1; // <- index is 11; does the
我是一名优秀的程序员,十分优秀!