C语言中复数运算及调用blas,lapack中复数函数进行科学计算

C语言中常用的数据类型主要int, float ,double ,char 等,但在科学运算中复数扮演着重要角色。这里讲下C语言中的复数运算以及如何调用blas,lapack库中的复数函数来进行科学计算.

1.C语言中的复数运算。

C语言中若要用的复数,需要包含头文件complex.h,下面看看一些基本的例子

#include <stdio.h>
#include"complex.h"

int main()
{
    complex a, b, c, d, f;
    a = 1 + 2*I;
    b = 3 + 4*I;
    c = a+b;
    d = a*b;
    f = a/b;
    printf("complex a plus b is :%f, %f\n", creal(c), cimag(c));
    printf("complex a multiply b is :%f, %f\n", creal(d), cimag(d));
    printf("complex a divided b is :%f, %f\n", creal(f), cimag(f));

}

说明:

(1).creal(c), cimag(c)表示分别去复数c的实部和虚部;

(2).complex 默认是complex double 型数据结构,即实部和虚部都是double 型,当然也可以定义complex int型;

  (3).虚数单位是用I来表示

生成可执行文件:

gcc -o test_complex test_complex1

得到的结果如下:

complex a plus b is :4.000000, 6.000000
complex a multiply b is :-5.000000, 10.000000
complex a / b is :0.440000, 0.080000

2.下面讲下如何利用调用blas的复函数来进行科学运算。

在blas,lapack中有三种表示复数的形式:利用C语言中的complex数据类型、结构体以及实部和复部交替存储。下面举例说明:

(1).利用C语言中complex数据类型

#include <stdio.h>
#include"stdlib.h"
#include"complex.h"

complex zdotu_(int *, complex *, int *,complex *, int *);    

int main()
{
    complex *bb, *cc, al;

    int i, j,  N, ONE=1;
    N =2;

    bb = malloc(N *sizeof(complex));
    cc = malloc(N *sizeof(complex));
        bb[0] = 1+I; bb[1]=1+I;
        cc[0] = 1+I; cc[1]=1+I;
        al= zdotu_(&N, cc, &ONE, bb, &ONE);
    printf("al:%f, %f\n", creal(al), cimag(al));

    free(bb);
    free(cc);
    return 0;
}

编译并生成可执行文件

gcc -o test_zdot.o -c test_zdot.c
gcc -o test_zdot test_zdot.c -lblas -lgfortran

执行:

./test_zdot

得到结果:

al:0.000000, 4.000000

(2).利用blas中定义的结构体CBLAS_TEST_ZOMPLEX

#include <stdio.h>
#include"stdlib.h"
#include"cblas_test.h"

#define zomplex CBLAS_TEST_ZOMPLEX 

zomplex zdotu_(int *, zomplex *, int *,zomplex *, int *);
int main()
{

    zomplex *b, *c , nal;
    int i, N, ONE=1;
    N =2;
    b = malloc(N *sizeof(zomplex));
    c = malloc(N *sizeof(zomplex));

    for(i=0; i< N; i++)
    {
        (*(b+i)).real = 1;
        (*(b+i)).imag = 1;
        (*(c+i)).real = 1;
        (*(c+i)).imag = 1;
    }

     nal= zdotu_(&N, b, &ONE, c, &ONE);
    printf("nal:%f, %f\n", nal.real, nal.imag);

    free(b);
    free(c);
    return 0;
}

说明:a. blas中在头文件cblas_test.h定义了结构体CBLAS_TEST_ZOMPLEX,其成员变量分别为:real, imag.

b.由于结构体CBLAS_TEST_ZOMPLEX的书写太长,例子中通过#define zomplex CBLAS_TEST_ZOMPLEX ,用zomplex来取代。

编译和(1)中一样,链接好blas, gfortran库即可,得到结果如下:

nal:0.000000, 4.000000

(3).利用实部和虚部交叉存储

在blas中定义了结构体,其在物理存储空间中,其实部和虚部都是交叉存储的,即存第一个数的实部,再存第一个数的虚部,第二个数的实部,第二个数的虚部...,那么也可以定义数组,交替存储实部和虚部。例子如下:

#include <stdio.h>
#include"stdlib.h"
#include"cblas_test.h"

#define zomplex CBLAS_TEST_ZOMPLEX
zomplex zdotu_(int *, double *, int *, double *, int *);
int main()
{

    zomplex al;
    double x[4], y[4];
    int i, j, N, ONE=1;
    N =2;

    x[0] = 1.0; x[1] = 1.0; x[2] = 1.0; x[3] = 1.0;
    y[0] = 1.0; y[1] = 1.0; y[2] = 1.0; y[3] = 1.0;

     al= zdotu_(&N, x,  &ONE, y, &ONE);
    printf("al:%f, %f\n", al.real, al.imag);

    return 0;
}

注意:函数声明如下:

zomplex zdotu_(int *, double *, int *, double *, int *); 

这里函数的形参数据类型为:double,而不是zomplex型了!!!

编译并执行,得到得到结果如下:

nal:0.000000, 4.000000

  根据自己的选用那种方式就需要声明哪种函数,因此在调用blas编程,需要先声明函数,以免出现意想不到的结果(从这三个例子中也可以看出,函数名一样,如果不声明函数的形参的数据类型,那得到的结果可能会有问题)。

调用lapack和blas类似,复数运算也是这三种方式,根据自己的喜好选择。

时间: 2024-12-20 03:04:49

C语言中复数运算及调用blas,lapack中复数函数进行科学计算的相关文章

Swift中利用AppDelegate实现调用指定ViewController中的函数

接着上一篇的Blog讲,在我们自定义了TableViewCell之后,我们可能需要点击cell里面的button等操作,比如点击了以后跳转到别的页面,这个时候,因为跳转动作是在tableview所在的viewcontroller(假设为A类)实现的,所以,我们需要在tablewViewCell类里面调用A类的一个实例,这个实例一般是通过AppDelegate类实现的. 具体来看一下实现过程. 我们先来看一下整体的需求: 在"基站列表"这个ViewController里面,我们的Tabl

Python中print和input调用了Python中底层的什么方法

print  print() 用 sys.stdout.write() 实现 import sys print('hello') sys.stdout.write('hello') print('new') # 结果: # hello # hellonew 可以看到两者还是有不同的. sys.stdout.write()结尾没有换行,而print()是自动换行的.另外,write()只接收字符串格式的参数. print()能接收多个参数输出,write()只能接收一个参数. input Pyth

InvocationHandler中invoke()方法的调用问题

转InvocationHandler中invoke()方法的调用问题 Java中动态代理的实现,关键就是这两个东西:Proxy.InvocationHandler,下面从InvocationHandler接口中的invoke方法入手,简单说明一下Java如何实现动态代理的.         首先,invoke方法的完整形式如下: public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

父框架调用子框架中内容的问题记录

有一个项目需要用框架来完成,在编码中发现父框架调用子框架中内容的实现有兼容性问题,特此记录下来! <iframe id="preview" name="preview" src="bill.php?page=preview" frameborder="0" width="100%"></iframe> 这个是我的框架,我准备操作框架中的DOM.所以我使用了, container= p

【C语言探索之旅】 第一部分第九课:函数

内容简介 1.课程大纲 2.第一部分第九课:函数 3.第一部分第十课预告: 练习题+习作 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写三个游戏. C语言编程基础知识 什么是编程? 工欲善其事,必先利其器 你的第一个程序 变量的世界 运算那点事 条件表达式 循环语句 实战:第一个C语言小游戏 函数 练习题 习作:完善第一个C语言小游戏 C语言高级技术 模块化编程 进击的指针,C语言王牌 数组 字符串 预处理 创建你自己的变量类型 文件读写 动

Swift 中的闭包与 C 和 Objective-C中的 blocks 以及其它一些编程语言中的 lambdas 比較类似。

闭包是功能性自包括模块,能够在代码中被传递和使用. Swift 中的闭包与 C 和 Objective-C中的 blocks 以及其它一些编程语言中的 lambdas 比較相似. 闭包能够 捕获 和存储其所在上下文中随意常量和变量的引用. 这就是所谓的闭合并包裹着这些常量和变量,俗称闭包.Swift会为您管理在 捕获 过程中涉及到的内存操作. 注意:假设您不熟悉 捕获 (capturing) 这个概念也不用操心.后面会具体对其进行介绍. 在Swift函数章节中介绍的全局和嵌套函数实际上也是特殊的

一些复数运算的C语言实现

很久不写博客了.第一次写博客是在04年,最近的一次还是在大学时,在学校时,甚至还有过自己去买虚拟主机搭WordPress写博客的经历.现在工作时间越长,越发现积累的重要性.那么就从这里开始吧,重新开始写博客. 最近打算写小算法,里面需要用到一些复数运算.贴一点复数运算的C语言实现代码.都是些很简单的东西. 包括以下运算: 复数加法.复数减法.复数乘法.复数除法.复数取模.复指数运算.复数取相角.模与相角合成复位.本人专业本职做硬件的,写程序没受过专业训练,勿吐槽. 1 /*file Comple

如何在c语言中源文件调用另一个源文件的函数

在源文件A1.c中调用A2.c 中的函数有两种方法: 1.在A2.c中有完整的函数定义,在A1.c中添加一下要用到的函数原型(声明)就可以了,例如:在A2.c中:有函数void A2(){...};在A1.c中:在文件前头增加一行:void A2();就可以了 2.把A2.c中完整定义的函数的原型,写到一个A2.h文件中,然后在A1.c的文件头增加#include "A2.h"就可以了以上两种方法,在A1.c中都可以正常的调用,就跟在A2.c中调用一样. 其实函数默认是外部的,只要在其

Learn Prolog Now 翻译 - 第五章 - 数字运算 - 第一节,Prolog中的数字运算

内容提要 Prolog中的数字运算 Porlog运算的本质 Prolog中的数字运算 Prolog语言本身提供了一些基础的运算符号,对整数进行一些操作(即类似...-3, -2, -1, 0, 1, 2, 3等).多数Prolog的实现同时也提供了一些工具对实数进行操作 (比如浮点数,1.53,6.35,等等).但是我们不会讨论浮点数,因为浮点数在典型的Prolog应用中很少,所以不是本文的重点.但是另一方面,整数是在Prolog 中有典型应用场景的(比如记录列表的长度),所以掌握起应用是十分重