Haskell 中 (^) 的奇怪行为

2024-01-16

为什么 GHCi 下面给出了错误的答案?

GHCi

λ> ((-20.24373193905347)^12)^2 - ((-20.24373193905347)^24)
4.503599627370496e15

Python3

>>> ((-20.24373193905347)**12)**2 - ((-20.24373193905347)**24)
0.0

UPDATE我将按如下方式实现 Haskell 的 (^) 函数。

powerXY :: Double -> Int -> Double
powerXY x 0 = 1
powerXY x y
    | y < 0 = powerXY (1/x) (-y)
    | otherwise = 
        let z = powerXY x (y `div` 2)
        in  if odd y then z*z*x else z*z

main = do 
    let x = -20.24373193905347
    print $ powerXY (powerXY x 12) 2 - powerXY x 24 -- 0
    print $ ((x^12)^2) - (x ^ 24) -- 4.503599627370496e15

尽管我的版本看起来并不比@WillemVanOnsem 下面提供的版本更正确,但奇怪的是,它至少给出了这种特殊情况的正确答案。

Python 也类似。

def pw(x, y):
    if y < 0:
        return pw(1/x, -y)
    if y == 0:
        return 1
    z = pw(x, y//2)
    if y % 2 == 1:
        return z*z*x
    else:
        return z*z

# prints 0.0
print(pw(pw(-20.24373193905347, 12), 2) - pw(-20.24373193905347, 24))

简短回答: 之间有区别(^) :: (Num a, Integral b) => a -> b -> a https://hackage.haskell.org/package/base-4.12.0.0/docs/Prelude.html#v:-94- and (**) :: Floating a => a -> a -> a https://hackage.haskell.org/package/base-4.12.0.0/docs/Prelude.html#v:-42--42-.

The (^)函数仅适用于整数指数。它通常会使用迭代算法,每次都会检查幂是否可被二整除,并将幂除以二(如果不可整除,则将结果乘以x)。因此,这意味着对于12,它将总共执行six乘法。如果乘法存在一定的舍入误差,则该误差可能会“爆炸”。正如我们在源代码 https://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.Real.html#%5E, the (^)函数实现为 https://github.com/ghc/ghc/blob/master/libraries/base/GHC/Float.hs#L377-L396:

(^) :: (Num a, Integral b) => a -> b -> a
x0 ^ y0 | y0 < 0    = errorWithoutStackTrace "Negative exponent"
        | y0 == 0   = 1
        | otherwise = f x0 y0
    where -- f : x0 ^ y0 = x ^ y
          f x y | even y    = f (x * x) (y `quot` 2)
                | y == 1    = x
                | otherwise = g (x * x) (y `quot` 2) x         -- See Note [Half of y - 1]
          -- g : x0 ^ y0 = (x ^ y) * z
          g x y z | even y = g (x * x) (y `quot` 2) z
                  | y == 1 = x * z
                  | otherwise = g (x * x) (y `quot` 2) (x * z) -- See Note [Half of y - 1]

The (**)函数是,至少对于Floats and Double实现在浮点单元上工作。事实上,如果我们看一下实施(**), 我们看:

instance Floating Float where
    -- …
    (**) x y = powerFloat x y
    -- …

这因此重定向到powerFloat# :: Float# -> Float# -> Float# https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-Exts.html#v:powerFloat-35-函数,通常由编译器链接到相应的 FPU 操作。

如果我们使用(**)相反,对于 64 位浮点单元,我们也得到零:

Prelude> (a**12)**2 - a**24
0.0

例如,我们可以用 Python 实现迭代算法:

def pw(x0, y0):
    if y0 < 0:
        raise Error()
    if y0 == 0:
        return 1
    return f(x0, y0)


def f(x, y):
    if (y % 2 == 0):
        return f(x*x, y//2)
    if y == 1:
        return x
    return g(x*x, y // 2, x)


def g(x, y, z):
    if (y % 2 == 0):
        return g(x*x, y//2, z)
    if y == 1:
        return x*z
    return g(x*x, y//2, x*z)

如果我们随后执行相同的操作,我会在本地得到:

>>> pw(pw(-20.24373193905347, 12), 2) - pw(-20.24373193905347, 24)
4503599627370496.0

这与我们得到的值相同(^)在 GHCi 中。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Haskell 中 (^) 的奇怪行为 的相关文章

  • “反向”使用 Maybe Monad

    假设我有很多功能 f a gt Maybe a g a gt Maybe a h a gt Maybe a 我想按以下方式组合它们 如果 f 返回 Nothing 则计算 g 如果 g 返回 Nothing 则计算 h 如果其中任何一个计算
  • 计算两点之间的距离(Haskell)

    给定两个元组的输入 我希望能够使用以下公式计算两点之间的距离 距离 sqrt x1 x2 2 y1 y2 2 所以我希望函数调用和输出如下所示 gt distance 5 10 3 5 5 385 当我尝试运行下面的代码时 它告诉我输入 w
  • 如何找到仅是 2、3 和 5 的幂的倍数的所有数字的列表? [复制]

    这个问题在这里已经有答案了 I am trying to generate a list of all multiples which can be represented by the form where a b and c are w
  • 将 Either 列表转换为其中包含列表的 Either 列表

    我是 Haskell 的初学者 我正在编写一些使用 Haskell 的代码Either https hackage haskell org package base 4 9 0 0 docs Data Either html用于错误处理 E
  • ARM、VFP、浮点、惰性上下文切换

    我正在为 ARM 处理器 Cortex A9 编写操作系统 我正在尝试实现浮点寄存器的延迟上下文切换 这背后的想法是 浮点扩展最初对线程禁用 因此不需要在任务切换上保存浮点上下文 当线程尝试使用浮点指令时 会触发异常 然后 操作系统启用浮点
  • 带有查询参数的渲染 url

    无法找到简单问题的解决方案 答案应该是显而易见的 如何在 hamlet 模板中使用查询参数渲染 url I e ItemsR 将生成http localhost 3000 items我如何生成类似的东西http localhost 3000
  • 在 C# 中测试两个双精度数相等的经验法则?

    假设我有一些代码可以执行一些浮点运算并将值存储在双精度数中 由于某些值无法用二进制完美表示 因此如何在合理的确定程度上测试相等性 如何确定 合理 的含义 Can double Epsilon以某种方式使用 Update 夫妇的事情 正如 h
  • 为什么 exceptT 没有 MonadMask 实例?

    爱德华 克梅特例外情况图书馆不提供单子掩码 https www stackage org haddock lts 7 18 exceptions 0 8 3 Control Monad Catch html t MonadMask实例为Ex
  • 使用 Haskell 将函数注入到 Java .class 文件中

    我使用 Haskell 编写了一个 Java 字节码解析器 它工作得很好 然而下一步让我完全难住了 我的 Haskell 程序需要修改 class 文件 以便在执行时 Java 程序打印 输入 此处的方法名称 在执行方法之前 并且 退出 此
  • 地图不是接受一个函数而列表返回一个列表吗?

    map2 List a gt b gt c gt a gt b gt c map2 List f map2 List f a as bs map f a bs map2 List f as bs 这是我的讲座中的一个示例 它尝试将二元函数应
  • 为什么编译时浮点计算可能不会得到与运行时计算相同的结果?

    In the speaker mentioned Compile time floating point calculations might not have the same results as runtime calculation
  • 没有由文字“1”产生的 Num String 实例

    main do putStrLn myLast 1 2 3 4 myLast a gt a myLast x x myLast xs myLast xs 当我尝试运行此代码时 我收到此消息 没有由文字 1 产生的 Num String 实例
  • 浮点运算的最佳实践

    我正在对精确到小数点后第二位的小数输入执行加法和减法 我试图通过乘以 100 将它们转换为整数来提高准确性 但效果却相反 考虑以下代码和输出 double d 2 01 int a int d 100 0 cout lt lt a lt l
  • 将浮点值转换为灰度十六进制颜色值

    这个问题又快又简单 我有一个二维浮点数组 0 0000000 到 1 0000000 我想将这些数字转换为颜色值 000000 到 ffffff 请注意 我所说的只是灰度值 0 黑色 0 5 中灰色 1 白色 有谁知道如何用 javascr
  • Haskell 中的多态函数作为参数

    我有一个带有两个构造函数的 ADT 一个包裹着一个Double和一个包裹着Integer 我想创建一个函数 它采用一元函数Numtypeclass 并返回一个函数 该函数将该一元函数应用于我的 ADT 的内容 我试过这个 data X Y
  • 如何在 x86 ASM 中将整数转换为浮点值?

    我需要将一个整数 二进制补码 乘以一个浮点常数 这是我所拥有的 data pi dd 3 14 int dd 0ah code fld pi fmul ST 1 ST 我怎样才能转换int乘以浮点值pi 你需要fild操作说明 这是一个参考
  • Haskell - 翻转具有两个参数的类型类的参数

    我有一个多参数类型类 它提供了一个可以交换其参数的函数 class Swappable a b where swappable a gt b gt Bool So if a and b form Swappable a b then b a
  • 数据类型变体之间的转换

    假设我想创建一种数据类型的两种变体 一种具有特定的构造函数 另一种没有它 否则它们是相同的 我想出了这个 LANGUAGE KindSignatures LANGUAGE DataKinds LANGUAGE GADTs data Foo
  • Haskell 中的所有图形和 Web 库是如何实现的?

    我才开始学习Haskell 我读到它是一种纯函数式语言 其中的所有内容都是不可变的 因此 输入输出 写入和读取数据库之类的事情会导致状态的可变性 我知道 Haskell 中有一种叫做 monad 的东西 它允许在 Haskell 中使用命令
  • Repa 数组上的并行 mapM

    在我最近的work https github com bgamari mixture model with Gibbs sampling 我一直在充分利用RVar http hackage haskell org packages arch

随机推荐

  • Log.e 不打印 UnknownHostException 的堆栈跟踪

    Calling Log e TAG some message e where e is an UnknownHostException 不会在 logcat 上打印堆栈跟踪 自2011年5月20日起 Log类 这样UnknownHostEx
  • 如何在ggplot2中通过点绘制45度线

    我有一个对数刻度的散点图 其中垂直和水平参考线穿过 1 1 下面的虚线 我想添加与虚线参考线成 45 度角的额外参考线 以便它们恰好平分虚线参考线创建的四个 部分 例如 下面我刚刚通过眼睛添加的较细实线 我怎样才能用 ggplot 做到这一
  • 使用任何 Android 设计支持库元素时出错

    从设计支持库中扩充任何内容时出错 xml
  • 如何从 Ruby on Rails 解析 json 数据或(json 代码)

    我有一个 Ruby on Rails 源代码 现在我想解析数据并发送数据 在我的代码中 它将从用户获取名称并显示它 如何解析 ROR 中的数据 这是我的controller rb代码 def index hotels Hotel all r
  • shell 文本编辑器如何工作?

    我对编程相当陌生 但我想知道 shell 文本编辑器 如 vim emacs nano 等 如何能够控制命令行窗口 我主要是一名 Windows 程序员 所以也许 nix 上的情况有所不同 据我所知 只能将文本打印到控制台并要求输入 文本编
  • 如何扫描 pandas 数据帧中所有大于某值的值并返回与该值对应的行号和列号?

    我有一个问题 我有如下所示的巨大数据集 相关系数矩阵 A B C D E A 1 0 413454352 0 615350574 0 479720098 0 34261232 B 0 413454352 1 0 568124328 0 31
  • 提交-拉-合并-推还是拉-合并-提交-推?

    我们几周前开始使用 Mercurial 大多数开发人员都遵循以下工作流程 致力于某项功能 commit m 致力于功能 ABC pull u If branch merge 提交 m 合并 push 今天 我们的一位开发人员建议我们这样做
  • Keras ImageDataGenerator 流程方法中的 save_to_dir 遇到问题

    我想保存 ImageDataGenerator 正在创建的增强图像 以便以后使用它们 当我执行以下代码时 它运行正常 但我希望保存的图像没有显示在我尝试保存它们的目录中 gen image ImageDataGenerator rotati
  • Future 任务完成后 Java 进程没有退出

    这是我使用 Future 的代码片段 import java util concurrent import java util public class FutureDemo public FutureDemo Future Executo
  • 更改或删除 App Store 中的开发者名称

    我已经为我的客户创建了一个应用程序 我们已经用我的帐户发布了该应用程序 现在 他们想将开发商名称更改为他们公司的名称 有没有办法更改开发商名称 我可以将我的应用程序移至他们的企业帐户 以便开发者名称更改为他们的企业名称吗 是的 自 WWDC
  • 阅读 Fetch Promise 的正文

    我有以下用于上传到 Google Cloud 存储的快速端点 它工作得很好 来自 google api 的响应给了我一个唯一的文件名 我想将其传回我的前端 app post upload req res gt var form new fo
  • Spring Boot 与 POM 打包聚合器

    是否可以使用 Spring Boots Maven 插件命令spring boot run当项目的父POM因其子项目而使用打包模式POM时 我有一个多模块 Maven 项目 其中有一个 主 POM 它又是 Spring Boot 父模块的子
  • iPhone内存警告级别=2

    我有一个应用程序 可以将大量视图堆叠在一起 在某些时候 我收到内存警告级别 2 这是预期的 问题是 当我运行 Instruments 时 我没有任何内存泄漏 并且该应用程序占用了大约 9 10MB 的空间 这不是that我会说很多吗 问题是
  • 如何根据属性查找两个数组列表之间的差异?

    我有两个数组列表 每个都有 Employee 类型的对象列表 Employee 类如下所示 public class Employee Employee String firstname String lastname String emp
  • 防止 Thread.CurrentPrincipal 跨应用程序域传播

    有人可以阻止当前线程的 IPrincipal 在应用程序域边界上传播吗 我无法控制分配给线程的 IPrincipal 但我可以控制创建应用程序域 我想要这样做的原因是为了防止在主要对象类型程序集在其他域中不可用时发生序列化错误 Edit E
  • 如何为 1x1 Android 小部件创建清晰的背景图像?

    我正在创建一个 1x1 小部件 无论我尝试什么 我都无法让背景图像看起来漂亮且清晰 我已经阅读了几乎所有我能找到的资源 但我仍然无法获胜 我正在为 HTC Desire Nexus 1 进行设计 希望有人告诉我在 Photoshop 中创建
  • 在 Node.JS 中引用相对于应用程序根目录的文件的正确方法

    我有一个在 AWS EC2 的 Linux 上运行的 Node JS 应用程序 它使用 fs 模块读取 HTML 模板文件 这是应用程序的当前结构 server js templates my template html services
  • Angular 6 迁移 -.angular-cli.json 到 angular.json

    我已经将我的项目升级到 Angular 6 除了转换之外一切都很顺利 angular cli json文件 从我遵循的指南来看 据说这会自动转换它 npm install g angular cli npm 安装 angular cli n
  • 构建 SparkSession

    我有在齐柏林飞艇担任翻译的火花 我使用的是Spark2 0 我构建了一个Session Create 一般来说 你不应该初始化SparkSession nor SparkContext在齐柏林飞艇 Zeppelin 笔记本配置为为您创建会话
  • Haskell 中 (^) 的奇怪行为

    为什么 GHCi 下面给出了错误的答案 GHCi gt 20 24373193905347 12 2 20 24373193905347 24 4 503599627370496e15 Python3 gt gt gt 20 2437319