找回密码
 注册
搜索
热搜: 超星 读书 找书
查看: 2759|回复: 24

[【解决】] 希望高手出手相助编一个用于两个多项式相乘的Karatsuba算法的C程序!

[复制链接]
发表于 2007-6-28 18:04:23 | 显示全部楼层 |阅读模式
上周,老师给我们出了这道题,由于涉及到调用函数,我不是很在行,没能处理 好调用函数的数组返回问题,所以一直调试不通!下周就要上交了,急!
希望高手能帮忙!
Karatsuba算法的思想主要是将乘法转化为加法来计算以减少计算复杂度,具体见附件,里面还附带一个用maple程序。
计算两个一元多项式(高次),希望能先宏定义一个程序所能计算的最高次数,用数组表示多项式,数组的坐标表示多项式的该项次数
最好能适用于整系数多项式和浮点型的多项式(实际上我觉得应该只是定义数组类型不同)
谢谢!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
回复

使用道具 举报

 楼主| 发表于 2007-6-28 19:05:58 | 显示全部楼层
快来高手啊!

帮帮忙啊!
回复

使用道具 举报

发表于 2007-6-28 23:56:01 | 显示全部楼层
计算机版赞助悬赏20财富。
回复

使用道具 举报

 楼主| 发表于 2007-6-29 08:49:38 | 显示全部楼层
只要能符合,能让我完成作业,肯定给加财富!(首先声明只提供两位,因为本人财富有限)
所写的程序最好有注释!谢谢!

希望版主能告诉我怎么给人加财富啊?
回复

使用道具 举报

 楼主| 发表于 2007-6-29 08:52:59 | 显示全部楼层
是右下角的评分那吗?
回复

使用道具 举报

发表于 2007-6-29 09:41:21 | 显示全部楼层
引用第2楼风影幻想于2007-06-28 23:56发表的 :
计算机版赞助悬赏20财富。

强烈支持

LZ可到茶馆宣传一下。
回复

使用道具 举报

 楼主| 发表于 2007-6-29 11:38:43 | 显示全部楼层
顶顶!!!!!!!!!!!!!!!!!
回复

使用道具 举报

发表于 2007-6-29 12:49:06 | 显示全部楼层
感觉应该到读书软件那里去发求助效率更高.
回复

使用道具 举报

发表于 2007-6-29 13:07:34 | 显示全部楼层
回复

使用道具 举报

 楼主| 发表于 2007-6-29 13:51:44 | 显示全部楼层
楼上给的链接,用的不是C,倒像是用汇编写的
到处都是用mov,cmp等语句
而且只是用于整数计算的(像是计算器内的整数乘法),不是多项式算法,
(可以说是特例)
不知理解对否?
回复

使用道具 举报

发表于 2007-6-29 16:24:30 | 显示全部楼层
头文件Karatsuba.h:
---------------------------------------------------------------------------------------------
#define MAX_INDEX 1000
#define NULL_VALUE -1e15
-----------------------------------------------------------------------------------------------
cpp文件Karatsuba.cpp:
------------------------------------------------------------------------------------------------
#include <stdio.h>
#include "math.h"
#include "Karatsuba.h"
#include <afx.h>
//得到最高指数
int Get_index(double f[MAX_INDEX])
{
  int i;
  for(i=0;i<MAX_INDEX;i++)
  {
    if(fabs(f-NULL_VALUE)<1e-6)
      return i-1;
  }
  return -1;
}
//得到指数的幂指数
int Get_n(double f[MAX_INDEX],double g[MAX_INDEX])
{
  double n1,n2;
  n1=(double)Get_index(f);
  n2=(double)Get_index(g);
  double maxn;
  if(n1>n2)
    maxn=n1;
  else
    maxn=n2;

  int ret;
  if(maxn==0)
    return 0;
  ret=(int)(log(maxn)/log(2))+1;
  return ret;
}
//判断是否有值
bool IsNull(double a)
{
  if(fabs(a-NULL_VALUE)<1e-6)
    return true;
  else
     return false;
}

//加法
bool Add(double f[MAX_INDEX],double g[MAX_INDEX],double result[MAX_INDEX])
{
  for(int i=0;i<MAX_INDEX;i++)
  {
    if(IsNull(f)&&IsNull(g))
    {
      return true;
    }
    else if(IsNull(f))
    {
      result=g;
    }
    else if(IsNull(g))
    {
      result=f;
    }
    else
    {
      result=g+f;
    }
  }
  return true;
}
//减法
bool Sub(double f[MAX_INDEX],double g[MAX_INDEX],double result[MAX_INDEX])
{
  for(int i=0;i<MAX_INDEX;i++)
  {
    if(IsNull(f)&&IsNull(g))
    {
      return true;
    }
    else if(IsNull(f))
    {
      result=0.0-g;
    }
    else if(IsNull(g))
    {
      result=f;
    }
    else
    {
      result=f-g;
    }
  }
  return true;
}
//Karatsuba算法
bool Karatsuba(double f[MAX_INDEX],double g[MAX_INDEX], double result[MAX_INDEX])
{
  int i;
  int n;
  n=Get_n(f,g);
  if(n==0)
  {
    result[0]=f[0]*g[0];
    return true;
  }
  double f1[MAX_INDEX],f0[MAX_INDEX],g1[MAX_INDEX],g0[MAX_INDEX];
  double f0g0[MAX_INDEX],f1g1[MAX_INDEX],f0af1[MAX_INDEX],g0ag1[MAX_INDEX],
    f0af1g0ag1[MAX_INDEX];
  double res1[MAX_INDEX],res2[MAX_INDEX],res3[MAX_INDEX],res4[MAX_INDEX],res5[MAX_INDEX];

  for(i=0;i<MAX_INDEX;i++)
  {
    f1=NULL_VALUE;
    f0=NULL_VALUE;
    g1=NULL_VALUE;
    g0=NULL_VALUE;
    f0g0=NULL_VALUE;
    f1g1=NULL_VALUE;
    f0af1=NULL_VALUE;
    g0ag1=NULL_VALUE;
    f0af1g0ag1=NULL_VALUE;
    res1=NULL_VALUE;
    res2=NULL_VALUE;
    res3=NULL_VALUE;
    res4=NULL_VALUE;
    res5=NULL_VALUE;
  }
  int sub_n;
  sub_n=1<<(n-1);
  n=1<<n;
  for(i=0;i<sub_n;i++)
  {
    f0=f;
    g0=g;
  }
  i=0;
  while(!IsNull(f[i+sub_n]))
  {
    f1=f[i+sub_n];
    i++;
  }
  if(IsNull(f1[0]))
    f1[0]=0.0;
  i=0;
  while(!IsNull(g[i+sub_n]))
  {
    g1=g[i+sub_n];
    i++;
  }
  if(IsNull(g1[0]))
    g1[0]=0.0;
  Karatsuba(f0,g0,f0g0);
  Karatsuba(f1,g1,f1g1);
  Add(f0,f1,f0af1);
  Add(g0,g1,g0ag1);
  Karatsuba(f0af1,g0ag1,f0af1g0ag1);

  i=0;
  while(!IsNull(f1g1))
  {
    res1[i+n]=f1g1;
    i++;
  }
  for(i=0;i<n;i++)
  {
    res1=0.0;
  }
  Sub(f0af1g0ag1,f0g0,res2);
  Sub(res2,f1g1,res3);

  
  i=0;
  while(!IsNull(res3))
  {
    res4[i+sub_n]=res3;
    i++;
  }
  for(i=0;i<sub_n;i++)
  {
    res4=0.0;
  }
  Add(res1,res4,res5);
  Add(res5,f0g0,result);
//去掉最高位的0
  i=0;
  while(!IsNull(result))
  {
    i++;
  }
  i--;
  while(result==0.0)
  {
    result=NULL_VALUE;
    i--;
  }
  return true;
}
main()
{
  double f[MAX_INDEX];
  double g[MAX_INDEX];
  double result[MAX_INDEX];
  int i;
//数组清空
  for(i=0;i<MAX_INDEX;i++)
  {
    f=NULL_VALUE;
    g=NULL_VALUE;
    result=NULL_VALUE;
  }
//初始化
  ///f(x)=1.0x0+2.0x1
  f[0]=1.0;
  f[1]=2.0;
  ///g(x)=1.0x0+1.0x1+2.0x2
  g[0]=1.0;
  g[1]=1.0;
  g[2]=3.0;

//乘法
  Karatsuba(f,g,result);


//显示结果
  CString msg;
  CString string_res;
  string_res="(";
  i=0;
  while(!IsNull(f[i+1]))
  {
    msg.Format("%.2fx%d+",f,i);
    string_res+=msg;
    i++;
  }
  
  msg.Format("%.2fx%d",f,i);
  string_res+=msg+")*(";
  i=0;
  while(!IsNull(g[i+1]))
  {
    msg.Format("%.2fx%d+",g,i);
    string_res+=msg;
    i++;
  }
  
  msg.Format("%.2fx%d",g,i);
  string_res+=msg+")=";
  i=0;
  while(!IsNull(result[i+1]))
  {
    msg.Format("%.2fx%d+",result,i);
    string_res+=msg;
    i++;
  }
  
  msg.Format("%.2fx%d\n",result,i);
  string_res+=msg;
  printf(string_res);
  return 0;
}------------------------------------------------------------------------------------------------------------------------------------

输出结果:
(1.00x0+2.00x1)×(1.00x0+1.00x1+3.00x2)=1.00x0+3.00x1+5.00x2+6.00x3
字符串部分偷了点懒,用了MFC的CString类 :)


ps: 这个算法好好玩:)第一次见到这样算多项式的。

贴源代码的文字时,系统好像自动去掉了一些中括号,楼主还是下载附件看吧。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
回复

使用道具 举报

 楼主| 发表于 2007-6-30 09:36:58 | 显示全部楼层
ret=(int)(log(maxn)/log(2))+1;这里似乎不该加1;
还有程序调试不通,好像缺少链接:LINK : fatal error LNK1104: cannot open file "nafxcwd.lib"
是不是你有意去掉的?还是漏传了?(此处我无论重新编译还是直接进dsw文件执行都是这个结果)
还有请教几个问题
里面你定义的那个MAX_INDEX可以不用赋值吗?
数组全部都用f=NULL_VALUE;这样是否等同于f=0.0;如若是这样的
那么
int Get_index(double f[MAX_INDEX])
{
  int i;
  for(i=0;i<MAX_INDEX;i++)
  {
    if(fabs(f-NULL_VALUE)<1e-6)//这里是否是说找最后一个不为0的系数,但是如果后面是一大堆0,该
//函数似乎不起作用了!请解释,谢谢!
      return i-1;
  }
  return -1;
}
希望能帮忙先调通,然后让我好试试是否是十几次二十几次的多项式相乘都能适用!
谢谢
回复

使用道具 举报

 楼主| 发表于 2007-6-30 09:44:41 | 显示全部楼层
同时希望有人能看看我的程序,帮忙看看函数调用那究竟是哪错了,最后就是没有输出
希望高手帮忙调试一下!
谢谢!
回复

使用道具 举报

 楼主| 发表于 2007-6-30 11:52:49 | 显示全部楼层
我的程序其中有个问题已找到!分解部分的多项式次数没有设定好
回复

使用道具 举报

 楼主| 发表于 2007-7-1 17:33:49 | 显示全部楼层
虽然找到了一个小问题,但是程序还是没有调通,
真不知怎么办!!!
快来个高手帮个忙啊!
回复

使用道具 举报

发表于 2007-7-3 11:16:21 | 显示全部楼层
你是用vc6.0 编译的么?

不好意思,出去玩了4天,刚刚回来看到你的留言...
回复

使用道具 举报

发表于 2007-7-3 11:25:47 | 显示全部楼层
NULL_VALUE 的值并不为零,它表示的是从该位起,以上的系数不存在。我设的是一个足够负的数(-1e-15),
我之所以并不把系数的默认值设为0,是为了提高计算速度,否则MAX_INDEX的值如果很大的话,那么多0代入一起计算,会耗费大量的cpu时间的。

ret=(int)(log(maxn)/log(2))+1的1是应该加的

比如说maxn=9
(int)(log(maxn)/log(2))=3;
2的3次方为8,是小于9的,而我们要得到的是大于9的最小的2的整数次幂。所以要加一。
回复

使用道具 举报

发表于 2007-7-3 11:38:27 | 显示全部楼层
刚才看了你的程序,你把所有高次数项的系数都毫无差别的设为0,这样程序执行的效率非常低下,个人认为。你要找一个最高次数都要遍历所有的系数...
回复

使用道具 举报

发表于 2007-7-3 11:47:06 | 显示全部楼层
哦,还有, nafxcwd.lib 是系统的静态链接库文件
在\Microsoft Visual Studio\VC98\MFC\Lib 目录下。
回复

使用道具 举报

 楼主| 发表于 2007-7-3 13:20:06 | 显示全部楼层
引用第18楼mudy于2007-07-03 11:47发表的 :
哦,还有, nafxcwd.lib 是系统的静态链接库文件
在Microsoft Visual StudioVC98MFCLib 目录下。
我这好像没有,所以调试不通,不知道是怎么回事!怪怪的
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|网上读书园地

GMT+8, 2024-5-12 17:35 , Processed in 0.489308 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表