为了创建double的任意精度浮点/插入替换,我尝试使用ffi包装MPFR,但是尽管我做了所有的努力,最简单的代码位还是不起作用。它编译,运行,但在假装工作了一段时间后,它却嘲弄地崩溃了。一个简单的C版本代码愉快地将数字“1”打印到(640个小数位)总共10000次。哈斯克尔的版本,当被要求做同样的事情时,会无声地腐蚀(?)只有289份打印出来的“1.0000…0000”和385份打印出来的数据会导致断言失败和爆炸。我不知道如何继续调试,因为它“应该可以工作”。
代码可在http://hpaste.org/10923处阅读,并在http://www.updike.org/mpfr-broken.tar.gz处下载。
我在FreeBSD6上使用的是GHC6.83,在MacOSX上使用的是GHC6.8.2。请注意,您需要安装MPFR(使用2.3.2进行测试),并为libs和头文件(以及gmp中的头文件)安装正确的路径(更改makefile)才能成功编译此文件。
问题
为什么c版本可以工作,而haskell版本却失效了?当我接近外国金融机构时,我还缺少什么?我试了一下稳定器,结果一模一样。
其他人可以通过编译和运行我的代码来验证这是否是mac/bsd唯一的问题吗?(C代码“有效”吗?haskell代码“noworks”有效吗?)Linux和Windows上的任何人都可以尝试编译/运行并查看是否得到相同的结果吗?
C代码:(works.C)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmp.h>
#include <mpfr.h>
#include "mpfr_ffi.c"
int main()
{
int i;
mpfr_ptr one;
mpf_set_default_prec_decimal(640);
one = mpf_set_signed_int(1);
for (i = 0; i < 10000; i++)
{
printf("%d\n", i);
mpf_show(one);
}
}
haskell代码:(main.hs---不起作用)
module Main where
import Foreign.Ptr ( Ptr, FunPtr )
import Foreign.C.Types ( CInt, CLong, CULong, CDouble )
import Foreign.StablePtr ( StablePtr )
data MPFR = MPFR
foreign import ccall "mpf_set_default_prec_decimal"
c_set_default_prec_decimal :: CInt -> IO ()
setPrecisionDecimal :: Integer -> IO ()
setPrecisionDecimal decimal_digits = do
c_set_default_prec_decimal (fromInteger decimal_digits)
foreign import ccall "mpf_show"
c_show :: Ptr MPFR -> IO ()
foreign import ccall "mpf_set_signed_int"
c_set_signed_int :: CLong -> IO (Ptr MPFR)
showNums k n = do
print n
c_show k
main = do
setPrecisionDecimal 640
one <- c_set_signed_int (fromInteger 1)
mapM_ (showNums one) [1..10000]
最佳答案
我也看到了问题
$ uname -a
Linux burnup 2.6.26-gentoo-r1 #1 SMP PREEMPT Tue Sep 9 00:05:54 EDT 2008 i686 Intel(R) Pentium(R) 4 CPU 2.80GHz GenuineIntel GNU/Linux
$ gcc --version
gcc (GCC) 4.2.4 (Gentoo 4.2.4 p1.0)
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 6.8.3
我还看到输出从1.0000…000变为1.0000…[垃圾]。
让我们看看,以下方法确实有效:
main = do
setPrecisionDecimal 640
mapM_ (const $ c_set_signed_int (fromInteger 1) >>= c_show) [1..10000]
这将问题缩小到在运行时受到某种程度的打击。不过,查看
one
和ghc -C
的输出并没有给我任何提示。嗯,
ghc -S
也可以工作,./noworks +RTS -H1G
对于不同的./noworks +RTS -k[n]k
值,以不同的方式演示失败。我没有可靠的线索,但有两种可能让我想到:
gmp,ghc运行时使用它,mpfr有一些奇怪的交互
ghc运行时内调用的c函数的堆栈空间有限,mpfr处理不好
有人说…有没有什么原因让您滚动自己的绑定而不是使用HMPFR?