Common LISP 和 Stack 中的数字类型边界在 GHCI 中流动

2024-02-22

第一个问题,Common LISP 和 Haskell 的新手,请友善。 我在 Common LISP 中有一个函数 - 下面的代码 - 旨在判断三角形的面积是否是整数(整数?)。

(defun area-int-p (a b c)
  (let* ((s (/ (+ a b c) 2))
         (area (sqrt (* s (- s a) (- s b) (- s c)))))
    (if (equal (ceiling area) (floor area))
        t
        nil)))

这应该使用海伦公式 https://en.wikipedia.org/wiki/Triangle#Using_Heron.27s_formula给定三边的大小,计算三角形的面积,并通过比较天花板和地板来确定它是否为整数。我们被告知,等边三角形的面积永远不是整数。因此,为了测试该函数是否正常工作,我使用参数运行了它333。这是我得到的回报:

CL-USER> (area-int-p 333 333 333)
NIL

完美的!有用。为了进一步测试它,我用参数运行它3333。这就是我得到的回报:

CL-USER> (area-int-p 3333 3333 3333)
T

出了什么问题,这不应该发生! 因此,我尝试使用以下希望等效的 Haskell 函数来看看会发生什么:

areaIntP :: (Integral a) => a -> a -> a -> Bool
areaIntP a b c =
  let aa = fromIntegral a
      bb = fromIntegral b
      cc = fromIntegral c
      perimeter = aa + bb + cc
      s = perimeter/2
      area = sqrt(s * (s - aa) * (s - bb) * (s - cc))
  in  if ceiling area == floor area
      then True
      else False

这就是我得到的:

*Main> areaIntP 3333 3333 3333
False
*Main> areaIntP 333 333 333
False

看起来很完美。受此启发,我在 Haskell 中使用以下函数来计算等腰三角形的周长总和,其中第三边与其他边仅相差一个单位,是一个积分面积,且周长低于 1,000,000,000。

toplamArtilar :: Integral a => a -> a -> a -> a
toplamArtilar altSinir ustSinir toplam =
  if ustSinir == altSinir
  then toplam
  else if areaIntP ustSinir ustSinir (ustSinir + 1) == True
       then toplamArtilar altSinir (ustSinir - 1) (toplam + (3 * ustSinir + 1))
       else toplamArtilar altSinir (ustSinir - 1) toplam

toplamEksiler :: Integral a => a -> a -> a -> a
toplamEksiler altSinir ustSinir toplam =
  if ustSinir == altSinir
  then toplam
  else if areaIntP ustSinir ustSinir (ustSinir - 1) == True
       then toplamEksiler altSinir (ustSinir - 1) (toplam + (3 * ustSinir - 1))
       else toplamEksiler altSinir (ustSinir - 1) toplam

sonuc altSinir ustSinir =
  toplamEksiler altSinir ustSinir (toplamArtilar altSinir ustSinir 0)

(ustSinir表示上限,altSinir顺便说一下下限。) 跑步sonuc与论据2 and 333333333然而,我的堆栈溢出了。在 Common LISP 堆栈中运行等效函数是可以的,但是area-int-p函数不可靠,可能是因为解释器推断的数字类型的边界。 毕竟,我的问题有两个:

1) 如何解决 Common LISP 函数中的问题area-int-p?

2) 如何在 Emacs 中或从终端运行 GHCi 时防止上述 Haskell 函数的堆栈溢出?

对于那些弄清楚我想在这里实现什么目标的人请注意:请不要告诉我使用 JavaBigDecimal and BigInteger.

在非常好的回复后进行编辑:我一并提出了两个问题,并从非常乐于助人的人那里收到了非常令人满意的、新手友好的答案和关于风格的注释。谢谢。


让我们定义一个中间 Common Lisp 函数:

(defun area (a b c)
  (let ((s (/ (+ a b c) 2)))
    (sqrt (* s (- s a) (- s b) (- s c)))))

您的测试给出:

CL-USER> (area 333 333 333)
48016.344

CL-USER> (area 3333 3333 3333)
4810290.0

在第二种情况下,应该清楚天花板和地板是相等的。 Haskell 中的情况并非如此,第二个测试(3333)返回:

4810290.040910754

浮点

在 Common Lisp 中,我们求平方根的值是:

370222244442963/16 

这是因为计算是用有理数进行的。到目前为止,精度是最大的。然而,SQRT http://clhs.lisp.se/Body/f_sqrt_.htm可以自由地返回有理数(如果可能)或近似结果。作为一种特殊情况,正如 Rainer Joswig 在评论中指出的那样,在某些实现上结果可以是整数。这是有道理的,因为两者integer and ratio是不相交的子类型rational类型。但正如您的问题所示,某些平方根是无理数(例如 √2),在这种情况下 CL 可以返回近似该值的浮点数(或复数浮点数)。

关于浮点数和数学函数的相关部分是12.1.3.3 浮点数可替换性规则 http://clhs.lisp.se/Body/12_acc.htm。长话短说,结果被转换为single-float当您计算平方根时,这会丢失一些精度。为了有一个双重,你必须更明确:

(defun area (a b c)
   (let ((s (/ (+ a b c) 2)))
     (sqrt (float (* s (- s a) (- s b) (- s c)) 0d0))))

我也可以用(coerce ... 'double-float), 但在这儿 我选择打电话给FLOAT http://clhs.lisp.se/Body/f_float.htm转换功能。可选的第二个参数是浮点原型,即。目标类型的值。上面,就是0d0,双浮点数。你也可以使用0l0对于长双打或0s0简而言之。如果您希望具有与输入浮点相同的精度,则此参数非常有用,但也可以与文字一起使用,如示例中所示。短、​​单、双或长浮点类型的确切含义是实现定义的,但它们应尊重一些规则 http://www.lispworks.com/documentation/HyperSpec/Body/t_short_.htm。当前的实现通常提供比最低要求更高的精度。

CL-USER> (area 3333 3333 3333)
4810290.040910754d0

现在,如果我想测试结果是否是整数,我会截断浮点数并查看第二个返回值(余数)是否为零。

CL-USER> (zerop (nth-value 1 (truncate 4810290.040910754d0)))
NIL

任意精度

请注意,无论使用哪种实现语言(Haskell、CL 或其他语言),考虑到浮点数的表示方式,该方法都会对某些输入给出错误的结果。事实上,对于某些具有更精确浮点数的输入,可能会出现与 CL 相同的问题,其中结果将非常接近整数。您可能需要另一种数学方法或类似的方法MPFR http://www.mpfr.org/用于任意精度浮点计算。 SBCL 附带sb-mpfr:

CL-USER> (require :sb-mpfr)
("SB-MPFR" "SB-GMP")

CL-USER> (in-package :sb-mpfr)
#<PACKAGE "SB-MPFR">

进而:

SB-MPFR> (with-precision 256
           (sqrt (coerce 370222244442963/16 'mpfr-float)))
.4810290040910754427104204965311207243133723228299086361205561385039201180068712e+7
-1
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Common LISP 和 Stack 中的数字类型边界在 GHCI 中流动 的相关文章

  • 在 Haskell 中将 Maybe Int 转换为 Int

    我正在编写以下代码 并希望找到框字符串中数字的索引 所以我用了findIndex但它返回Maybe Int值 而我只想要Int value 我怎样才能转换Maybe Int to Int值或者有什么方法可以提取Int from Maybe
  • 由于标志字节串 -lt-0_10_4,无法使用 Stack 构建 hello world 程序

    通过生成一个裸露的 hello world 项目 stack new myproject simple 每当我跑步时stack setup stack init or stack build我总是出现以下错误 Downloading lts
  • 移动列表中特定元素的简单函数

    我是 Haskell 的新手 我正在尝试弄清楚如何创建一个函数 shift Eq a gt a gt a gt Int gt a shift x h t z 输入 一个通用列表和一个相同类型的元素 x 前提条件 元素x存在于列表中 Outp
  • 用parsec解析递归数据

    import Data Attoparsec Text Lazy import Data Text Lazy Internal Text import Data Text Lazy pack data List a Nil Cons a L
  • 在 Haskell 中将字节转换为 Int64s/Floats/Doubles

    我正在尝试解析 Haskell 中的二进制文件格式 Apple 的二进制属性列表格式 该格式所需的内容之一是将字节序列视为 a 无符号 1 2 或 4 字节整数 b 有符号 8 字节整数 c 32 位floats d 64 位doubles
  • 通过 Emacs 评估 ghci 或 Hugs 中的缓冲区

    在 Emacs 中使用 sml mode 我已经能够使用以下命令将缓冲区内容直接发送到较差的 SML 进程C c C b 现在我只想用 Haskell 做同样的事情 Haskell 模式似乎不支持这一点 所以我想知道 使用 Emacs 和
  • Haskell,optparse-generic 的未命名命令行参数

    我在用着optparse 通用 https hackage haskell org package optparse generic解析名为的程序的命令行参数example 我有一个带有命名字段的数据类型 记录语法 例如 data Exam
  • 整数转浮点数

    这段代码的工作原理 posToXY Float gt Float gt Integer posToXY a b do let y a b round y 但这不起作用 posToXY Integer gt Integer gt Intege
  • 访问函数中的环境

    In main我可以读取我的配置文件 并将其提供为runReader somefunc myEnv正好 但somefunc不需要访问myEnv读者提供 链中的下一对也没有提供 需要 myEnv 中某些内容的函数是一个微小的叶函数 如何在不将
  • 如何为强制长度为 2^n 的向量类型定义可用的 Applicative 实例

    对于某些应用程序 我需要长度为 2 n 的向量 为了强制某些操作的长度匹配 我使用 ist 应用实例定义了我的类型 如下所示 LANGUAGE GADTs DataKinds FlexibleInstances FlexibleContex
  • 如何从 haskell 中的 IOError 获取 errno?

    我在 haskell 平台上 GHC 6 12 1 作为 apt get 安装在 Debian Squeeze 上 鉴于我需要在与最初引发它的线程不同的线程上使用它 如何从 IOError 中获取底层 errno 我需要这个的原因是因为我正
  • 在 Haskell 中计算移动平均线

    我正在学习 Haskell 所以我尝试实现移动平均函数 这是我的代码 mAverage Int gt Int gt Float mAverage x a fromIntegral k fromIntegral x k lt rawAvera
  • Haskell 类型系统的细微差别

    我一直在深入了解 haskell 类型系统的本质 并试图了解类型类的要点 我已经学到了很多东西 但我在下面的代码片段上遇到了困难 使用这些类和实例定义 class Show a gt C a where f Int gt a instanc
  • 为什么 Haskell 的默认字符串实现是一个字符链接列表?

    Haskell 默认值的事实String众所周知 实现在速度和内存方面都效率不高 据我所知 lists一般来说 在 Haskell 中实现为单链表 并且适用于大多数小型 简单数据类型 例如Int 这似乎不是一个好主意 但是对于String这
  • 为什么在 emacs-lisp 中的函数参数之前使用#'?

    我熟悉 Emacs Lisp 但不熟悉 Common 或任何其他 Lisp 一些 Lisp 程序员建议 例如emacs 的基本功能 https stackoverflow com questions 17076646 a basic fun
  • 从 CCL 检索(加载)源代码?

    我打了电话 load code lisp 用CCL 然后不小心删除了code lisp 有什么办法可以找回源代码吗 CCL 在内存中是否有它 这是一个非常特殊的功能 这里只为克洛祖尔CL 该代码在其他地方不起作用 这在 CCL IDE 中对
  • Haskell - 用防护罩替换外壳

    我想知道在这部分代码中是否可以用守卫替换 case 语句 firstFunction String gt Maybe MyType secondFunction MyType gt Integer myFunction String gt
  • 使用 FoldLine 解析多个块

    对于这个简化的问题 我试图解析一个如下所示的输入 foo bar baz quux woo hoo xyzzy glulx into foo bar baz quux woo hoo xyzzy glulx 我尝试过的代码如下 import
  • Haskell Stack 从 github 安装包依赖项

    是否可以使用 Haskell 堆栈从 github 安装软件包的版本 例如在一个 cabal or a stack yaml文件 如何在 git repo branch revision 上指向依赖项 对于堆栈 The 的文档stack y
  • Haskell:Data.Numbers.Primes 库在哪里?

    我尝试导入 Data Numbers Primes import Data Numbers Primes 伦哈斯克尔给了我 5 hs 1 8 Could not find module Data Numbers Primes Use v t

随机推荐

  • 如何在 Bokeh 中添加文本注释?

    我正在寻找 Matplotlib 类型1 http matplotlib org 1 4 0 users annotations intro htmlBokeh 中的文本注释 但我在他们的用户指南中找不到它2 http bokeh pyda
  • 分析 DNA 序列中的串联重复基序

    嘿 伙计们 由于我是编码世界和 Python 的新手 因此我没有太多编码经验 因此我们将不胜感激 我正在处理 DNA 序列中的短串联重复 我希望有一个代码可以根据指定位点的串联基序读取和计算重复的核苷酸 这是我需要的一个例子 串联图案 AG
  • 如何在 Streamlit 中设置按钮样式

    我的应用程序中有一个按钮 我想在用户单击它时对其进行样式设置 问题是 因为 Streamlit 不允许我们向我们创建的对象发出类 所以我需要找到一种方法来以稳健且与版本无关的方式指定确切的按钮 这是按钮在 Streamlit 中的样子 di
  • 如何使用 vscode 终端打开文件?

    我想打开一个新选项卡并使用打开一个文件vscode终端 like open somefile js命令 所以我可以使用ls并快速打开文件 Use code r
  • Flask 不提供图片

    我创建了一个小型 Flask 应用程序 用于处理和呈现本地计算机上本地使用的数据 我的 Flask 应用程序处理子文件夹中的数据 然后打开网页来显示处理后的数据 除了没有提供图像之外 一切看起来都很棒 例如 生成的 HTMl 源将具有以下内
  • Java中布尔表达式求值顺序?

    假设我有以下表达式 String myString getStringFromSomeExternalSource if myString null myString trim length 0 Eclipse 警告我myString布尔表
  • 如何使用windows cmd查看用户权限?

    我正在尝试使用 Windows 中的命令提示符查看用户权限 用户帐户和用户权限 例如 SeBatchLogonRight SeDenyBatchLogonRight SeInteractiveLogonRight SeDenyInterac
  • 登录到控制台而不是减速器操作内的代理对象时如何查看状态?

    使用时console log 在减速器操作内 状态打印为代理对象 而不是我实际想要查看的对象 我怎样才能看到实际的物体 我正在使用 redux starter kit createSlice 我不确定这是否与之有关 import creat
  • 区块链可以存储在 SQL 甚至 noSQL 数据库中吗?

    我读过 区块链数据库不存储在任何单一位置 这意味着它保存的记录是真正公开的并且易于验证 此信息不存在可供黑客破坏的集中版本 它的数据由数百万台计算机同时托管 互联网上的任何人都可以访问 所以我的问题是我们可以将区块链存储在例如 sql 中吗
  • 如何将ScrollView滚动到文本中的特定位置[重复]

    这个问题在这里已经有答案了 我有一个 ScrollView 里面有一个 TextView 我想将它滚动到某个段落 就像 HTML 中的锚点一样 例如 page html paragraph id 有人知道怎么做吗 Thanks 尝试使用sc
  • 在 CDI 中指定不同的子类实现

    我有两个类 A 和 B 需要使用服务 有两个服务 S1 和 S2 S2 扩展了 S1 我希望将 S1 注入 A 类 将 S2 注入 B 类 我如何在 CDI 中完成此操作 public class S1 public class S2 ex
  • 如何将多首歌曲/曲目加载到pygame中?

    有没有办法将多首歌曲加载到 Pygame 中 我说的不是这样的音效 crash sound pygame mixer Sound crash ogg and pygame mixer Sound play crash 因为我知道显然你可以有
  • Restlet 获取 HTTP 状态代码 204 而不是 200

    对于第一个请求 我收到 JSON 响应 从下一个请求开始 我开始获取此日志和 HTTP 状态代码 204 即使 ServerResource 已成功返回表示 org restlet engine adapter ServerAdapter
  • PHP MySQL 自动完成

    我有一个自动完成搜索字段 当用户输入名称时 结果会显示在下拉列表中 这一切都工作正常 并按应有的方式显示数据 然而 我正在等待将每个结果设为链接 因此当显示结果时 用户可以单击正确的名称 然后将他们带到他们的个人资料 请参阅下面的脚本
  • XML 检测调试模式

    我知道我可以通过编程方式使用 if BuildConfig DEBUG do something for a debug build 但是 我想做的是在调试模式下显示水印 有没有办法在 XML 文件中执行类似的操作 现在可以用数据绑定库 h
  • matplotlib 极坐标二维直方图

    我试图在极轴上绘制一些直方图数据 但它似乎无法正常工作 下面是一个例子 我使用找到的自定义投影如何使 matplotlib 极坐标图中的角度顺时针旋转 顶部为 0 https stackoverflow com questions 2417
  • Xcode 6:Fabric Crashlytics 更新后找不到“Answers.h”文件

    我正在 Xcode 6 3 2 中的 Objective C 项目中编写故事板 突然 当我尝试构建时出现错误 Developer ProjectName Crashlytics framework Headers Crashlytics h
  • 用于托管 MySQL 数据库的 Cloud SQL 或虚拟机实例

    我有一个网站 但我很困惑在哪里托管其数据库 Google Cloud SQL D1 层具有 0 5 GB RAM 其费用为每天 1 46 美元 GCE n1 standard 2 有 7 5 GB RAM 其成本为每天 1 68 我将当前的
  • Azure 管道在解析管道 YAML(唯一作业名称)时遇到错误

    在我的 azure devops 项目中 我使用模板创建了一个管道 这是我的构建管道的主要 yaml 文件 name Test Date yyyyMMdd Rev r resources repositories repository ap
  • Common LISP 和 Stack 中的数字类型边界在 GHCI 中流动

    第一个问题 Common LISP 和 Haskell 的新手 请友善 我在 Common LISP 中有一个函数 下面的代码 旨在判断三角形的面积是否是整数 整数 defun area int p a b c let s a b c 2