gpt4 book ai didi

haskell - Haskell 中的舍入 NaN

转载 作者:行者123 更新时间:2023-12-02 07:24:19 26 4
gpt4 key购买 nike

令我惊讶的是,我发现在 Haskell 中对 NaN 值进行舍入会返回一个巨大的负数:

round (0/0)
-269653970229347386159395778618353710042696546841345985910145121736599013708251444699062715983611304031680170819807090036488184653221624933739271145959211186566651840137298227914453329401869141179179624428127508653257226023513694322210869665811240855745025766026879447359920868907719574457253034494436336205824

地板和天花板也会发生同样的情况。

这里发生了什么?这种行为是故意的吗?当然,我知道任何不希望这种行为的人总是可以编写另一个检查 isNaN 的函数 - 但是是否存在更明智地处理 NaN 的现有替代标准库函数(对于“更明智”的某些定义)?

最佳答案

TL;DR: NaN具有 2 ^ 1024 之间的任意表示和2 ^ 1025 (不包括边界)和 - 1.5 * 2 ^ 1024 (这是一种可能)NaN恰好是你击中的那个。

<小时/>

为什么任何推理都是错误的

What is happening here?

您正在进入未定义行为的区域。或者至少在其他一些语言中你会这样调用它。该报告定义了round如下:

6.4.6 Coercions and Component Extraction

The ceiling, floor, truncate, and round functions each take a real fractional argument and return an integral result. … round x returns the nearest integer to x, the even integer if x is equidistant between two integers.

在我们的例子中x一开始并不代表数字。根据6.4.6,y = round x应该满足任何其他 z来自round的共域具有相等或更大的距离:

y = round x ⇒ ∀z : dist(z,x) >= dist(y,x)

但是,数字的距离(又称减法)仅针对数字定义。如果我们使用

dist n d = fromIntegral n - d

我们很快就会遇到麻烦:任何包含 NaN 的操作将返回NaN再次比较NaN失败,所以我们上面的属性不适合任何z如果xNaN首先。如果我们检查 NaN ,我们可以返回任何值,但是我们的属性适用于所有对:

dist n d = if isNaN d then constant else fromIntegral n - d

所以我们在 round x 上完全是任意的。如果 x 将返回不是一个数字。

为什么我们会得到这么大的数字?

“好吧”,我听到你说,“这一切都很好,但为什么我会得到这个号码?”这是个好问题。

Is this behavior intended?

有点。这并不是真正的意图,而是预期。首先我们要知道怎么Double作品。

IEE 754 double float

一个Double Haskell 中通常是符合 IEEE 754 标准的 double float ,即具有 64 位的数字,用

x = s * m * (b ^ e)

哪里s是一位,m是尾数(52 位)和 e是指数(11 位, floatRange )。 b是基础,通常是 2 (您可以通过 floadRadix 检查)。由于 m 的值已标准化,每个格式良好 Double具有独特的代表性。

IEEE 754 NaN

除了NaNNaN表示为 emax+1、以及非零尾数。所以如果位域

SEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM

代表Double ,表示 NaN 的有效方式是什么? ?

?111111111111000000000000000000000000000000000000000000000000000
^

即单个M设置为1 ,其他的没必要设置这个概念。符号是任意的。为什么只有一点?因为它足够了。

将 NaN 解释为 Double

现在,当我们忽略这是一个格式错误的 Double 的事实时—a NaN – 真的,真的真的想要将其解释为数字,我们会得到什么数字?

m = 1.5
e = 1024

x = 1.5 * 2 ^ 1024
= 3 * 2 ^ 1024 / 2
= 3 * 2 ^ 1023

你瞧,这正是您得到的数字 round (0/0) :

ghci> round $ 0 / 0
-269653970229347386159395778618353710042696546841345985910145121736599013708251444699062715983611304031680170819807090036488184653221624933739271145959211186566651840137298227914453329401869141179179624428127508653257226023513694322210869665811240855745025766026879447359920868907719574457253034494436336205824
ghci> negate $ 3 * 2 ^ 1023
-269653970229347386159395778618353710042696546841345985910145121736599013708251444699062715983611304031680170819807090036488184653221624933739271145959211186566651840137298227914453329401869141179179624428127508653257226023513694322210869665811240855745025766026879447359920868907719574457253034494436336205824

这让我们的小冒险停止了。我们有一个NaN ,这会产生 2 ^ 1024 ,并且我们有一些非零尾数,它产生的结果的绝对值在 2 ^ 1024 < x < 2 ^ 1025 之间.

请注意,这不是唯一的方法 NaN可以得到代表:

In IEEE 754, NaNs are often represented as floating-point numbers with the exponent emax + 1 and nonzero significands. Implementations are free to put system-dependent information into the significand. Thus there is not a unique NaN, but rather a whole family of NaNs.

有关详细信息,请参阅classic paper on floating point numbers by Goldberg .

关于haskell - Haskell 中的舍入 NaN,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44379638/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com