Windows服务程序访问NAS

由于服务程序授权与用户桌面授权互不影响,所以即使在用户桌面映射了NAS盘符,在Windows服务程序下仍然是不可以访问的。

一般来说有这样几种做法来访问NAS或共享盘:
1、加入域,通过“域用户认证”或“通过将NAS资源设置对某台计算机授权”来达到访问NAS的目的
2、不加域,在Windows中添加与NAS相同的用户名及密码,服务程序通过该用户名密码登录,可以访问NAS
3、不加域,通过调阅API的方式来获得访问NAS的权限
A、VC实现如下:

DWORD AcessNetDrtive(TCHAR* szRemotePath, TCHAR* szLocalDriver,  const TCHAR* szUsername, const TCHAR* szPassword)
{
	DWORD dwRetVal;
	DWORD dwFlags;

	NETRESOURCE nr;
	memset(&nr, 0, sizeof(NETRESOURCE));
	nr.dwScope = RESOURCE_GLOBALNET;
	nr.dwType = RESOURCETYPE_ANY;
	nr.lpLocalName = szLocalDriver;
	nr.lpRemoteName = szRemotePath;
	nr.lpProvider = NULL;

	//CONNECT_REDIRECT;CONNECT_UPDATE_PROFILE;
	dwFlags = 0;
	dwRetVal = WNetAddConnection2(&nr, szPassword, szUsername, dwFlags);

	retrun dwRetVal;
}

B、C#实现如下:

    public class NetworkDrive
    {
        public enum ResourceScope
        {
            RESOURCE_CONNECTED = 1,
            RESOURCE_GLOBALNET,
            RESOURCE_REMEMBERED,
            RESOURCE_RECENT,
            RESOURCE_CONTEXT
        }

        public enum ResourceType
        {
            RESOURCETYPE_ANY,
            RESOURCETYPE_DISK,
            RESOURCETYPE_PRINT,
            RESOURCETYPE_RESERVED
        }

        public enum ResourceUsage
        {
            RESOURCEUSAGE_CONNECTABLE = 0x00000001,
            RESOURCEUSAGE_CONTAINER = 0x00000002,
            RESOURCEUSAGE_NOLOCALDEVICE = 0x00000004,
            RESOURCEUSAGE_SIBLING = 0x00000008,
            RESOURCEUSAGE_ATTACHED = 0x00000010,
            RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED),
        }

        public enum ResourceDisplayType
        {
            RESOURCEDISPLAYTYPE_GENERIC,
            RESOURCEDISPLAYTYPE_DOMAIN,
            RESOURCEDISPLAYTYPE_SERVER,
            RESOURCEDISPLAYTYPE_SHARE,
            RESOURCEDISPLAYTYPE_FILE,
            RESOURCEDISPLAYTYPE_GROUP,
            RESOURCEDISPLAYTYPE_NETWORK,
            RESOURCEDISPLAYTYPE_ROOT,
            RESOURCEDISPLAYTYPE_SHAREADMIN,
            RESOURCEDISPLAYTYPE_DIRECTORY,
            RESOURCEDISPLAYTYPE_TREE,
            RESOURCEDISPLAYTYPE_NDSCONTAINER
        }

        [StructLayout(LayoutKind.Sequential)]
        private class NETRESOURCE
        {
            public ResourceScope dwScope = 0;
            public ResourceType dwType = 0;
            public ResourceDisplayType dwDisplayType = 0;
            public ResourceUsage dwUsage = 0;
            public string lpLocalName = null;
            public string lpRemoteName = null;
            public string lpComment = null;
            public string lpProvider = null;
        }

        [DllImport("mpr.dll")]
        private static extern int WNetAddConnection2(NETRESOURCE lpNetResource, string lpPassword, string lpUsername, int dwFlags);

        public static int MapNetworkDrive(string remotePath, string localDrive, string userName, string passWord)
        {
            NETRESOURCE myNetResource = new NETRESOURCE();
            myNetResource.lpLocalName = localDrive;
            myNetResource.lpRemoteName = remotePath;
            myNetResource.lpProvider = null;
            int result = WNetAddConnection2(myNetResource, passWord, userName, 0);
            return result;
        }
    }

IIS程序访问NAS

IIS程序访问NAS,一般有两种情况,加域和没加域
1、加域后,什么都好办,可以通过两种方式认证
A、采用域帐户认证
B、NAS资源可以直接授权给指定计算机访问

2、不加域,那一般有三种方式设置访问权限
A、通过指定程序的用户名和密码访问(这里指定的不是本地的用户名和密码,而是NAS的用户名和密码)
B、不指定用户名和密码,直接通过pass-through authentication方式访问,其规则为:
首先通过用户的真实id进行验证
如果用户没有授权,会尝试使用应用池的账户进行验证
如果应用池账号为NetworkService或LocalSystem,将使用计算机账号进行验证
采取这样的方式IIS会提出警告,因为IIS只有在运行之后,才知道能否访问NAS
C、通过代码实现

    //NAS访问封装类
    public class NetworkDrive
    {
        public enum ResourceScope
        {
            RESOURCE_CONNECTED = 1,
            RESOURCE_GLOBALNET,
            RESOURCE_REMEMBERED,
            RESOURCE_RECENT,
            RESOURCE_CONTEXT
        }

        public enum ResourceType
        {
            RESOURCETYPE_ANY,
            RESOURCETYPE_DISK,
            RESOURCETYPE_PRINT,
            RESOURCETYPE_RESERVED
        }

        public enum ResourceUsage
        {
            RESOURCEUSAGE_CONNECTABLE = 0x00000001,
            RESOURCEUSAGE_CONTAINER = 0x00000002,
            RESOURCEUSAGE_NOLOCALDEVICE = 0x00000004,
            RESOURCEUSAGE_SIBLING = 0x00000008,
            RESOURCEUSAGE_ATTACHED = 0x00000010,
            RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED),
        }

        public enum ResourceDisplayType
        {
            RESOURCEDISPLAYTYPE_GENERIC,
            RESOURCEDISPLAYTYPE_DOMAIN,
            RESOURCEDISPLAYTYPE_SERVER,
            RESOURCEDISPLAYTYPE_SHARE,
            RESOURCEDISPLAYTYPE_FILE,
            RESOURCEDISPLAYTYPE_GROUP,
            RESOURCEDISPLAYTYPE_NETWORK,
            RESOURCEDISPLAYTYPE_ROOT,
            RESOURCEDISPLAYTYPE_SHAREADMIN,
            RESOURCEDISPLAYTYPE_DIRECTORY,
            RESOURCEDISPLAYTYPE_TREE,
            RESOURCEDISPLAYTYPE_NDSCONTAINER
        }

        [StructLayout(LayoutKind.Sequential)]
        private class NETRESOURCE
        {
            public ResourceScope dwScope = 0;
            public ResourceType dwType = 0;
            public ResourceDisplayType dwDisplayType = 0;
            public ResourceUsage dwUsage = 0;
            public string lpLocalName = null;
            public string lpRemoteName = null;
            public string lpComment = null;
            public string lpProvider = null;
        }

        [DllImport("mpr.dll")]
        private static extern int WNetAddConnection2(NETRESOURCE lpNetResource, string lpPassword, string lpUsername, int dwFlags);

        public static int MapNetworkDrive(string remotePath, string localDrive, string userName, string passWord)
        {
            NETRESOURCE myNetResource = new NETRESOURCE();
            myNetResource.lpLocalName = localDrive;
            myNetResource.lpRemoteName = remotePath;
            myNetResource.lpProvider = null;
            int result = WNetAddConnection2(myNetResource, passWord, userName, 0);
            return result;
        }
    }

    //调用示例
    NetworkDrive.MapNetworkDrive("NAS paht with ip", "Local Driver Letter", "user", "password");

参考资料:
What is “pass-through authentication” in IIS 7?

不支持一个STA线程上针对多个句柄的WaitAll

最近项目中用了COM控件,同时也用了多线程,在等待线程退出的地方,使用了

AutoResetEvent[] tEevents;
//...
WaitHandle.WaitAll(tEevents);

程序运行到这里,就会报错:

不支持一个STA线程上针对多个句柄的WaitAll

当时事情很急,将其调整为

AutoResetEvent[] tEevents;
//...
foreach(var tEvent in tEevents)
{
    tEvent.WaitOne();
}

就将这个问题绕了过去。

后来,在Stackoverflow上面,查了STA和MTA的区别。COM线程模型称为Apartment模型,分为STA和MTA两种。
STA(Single Thread Apartment)
STA是非线程安全的,常用于UI界面,其他线程要访问STA模式的COM组件,需要通过STA线程进行访问(其实就变成了单线程调用)
MTA(Multi Thread Apartment)
MTA是线程安全的,COM的程序员自己处理了并发的问题,其他线程可以直接访问COM组件

参考资料:
Could you explain STA and MTA?

语法插件从WP-Syntax替换为SyntaxHighlighter Evolved

今天正好有些时间,索性将语法插件从WP-Syntax替换为SyntaxHighlighter Evolved。

由于是通过后台SQL进行处理的,出现了不少问题,经过3小时奋战,还是调整的差不多了。

现在有两个问题:
1、太长的代码要么不换行,要么换行不好看
2、有些语法不支持,如per,Io,go等
3、应该还有一些SQL操作的遗留问题,后面发现再调整吧

	'as3'           => 'as3',
	'actionscript3' => 'as3',
	'bash'          => 'bash',
	'shell'         => 'bash',
	'coldfusion'    => 'coldfusion',
	'cf'            => 'coldfusion',
	'clojure'       => 'clojure',
	'clj'           => 'clojure',
	'cpp'           => 'cpp',
	'c'             => 'cpp',
	'c-sharp'       => 'csharp',
	'csharp'        => 'csharp',
	'css'           => 'css',
	'delphi'        => 'delphi',
	'pas'           => 'delphi',
	'pascal'        => 'delphi',
	'diff'          => 'diff',
	'patch'         => 'diff',
	'erl'           => 'erlang',
	'erlang'        => 'erlang',
	'fsharp'        => 'fsharp',
	'groovy'        => 'groovy',
	'java'          => 'java',
	'jfx'           => 'javafx',
	'javafx'        => 'javafx',
	'js'            => 'jscript',
	'jscript'       => 'jscript',
	'javascript'    => 'jscript',
	'latex'         => 'latex', // Not used as a shortcode
	'tex'           => 'latex',
	'matlab'        => 'matlabkey',
	'objc'          => 'objc',
	'obj-c'         => 'objc',
	'perl'          => 'perl',
	'pl'            => 'perl',
	'php'           => 'php',
	'plain'         => 'plain',
	'text'          => 'plain',
	'ps'            => 'powershell',
	'powershell'    => 'powershell',
	'py'            => 'python',
	'python'        => 'python',
	'r'             => 'r', // Not used as a shortcode
	'splus'         => 'r',
	'rails'         => 'ruby',
	'rb'            => 'ruby',
	'ror'           => 'ruby',
	'ruby'          => 'ruby',
	'scala'         => 'scala',
	'sql'           => 'sql',
	'vb'            => 'vb',
	'vbnet'         => 'vb',
	'xml'           => 'xml',
	'xhtml'         => 'xml',
	'xslt'          => 'xml',
	'html'          => 'xml',

2014版MAC分区失败(后记)

等了一个月,MAC一直卡在“加密已暂停,连接电源适配器”,当然不管插不插电,结果是一样的。
重启到command+r,关闭FileVault,还是不行。

好吧,这是逼着我干掉你了。
1、将MAC备份为移动硬盘上的映像文件。
2、重启进入MAC,用Time Mashine同样备份到移动硬盘上。
3、重启到command+r
4、磁盘工具,干掉当前分区
5、重建分区(不带加密的那个)
6、Time Mashine还原
7、重启进入MAC
8、Bootcamp分区,安装Win7,搞定!

CS进程单例模式

1、SingletonExeController.cs

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace SingletonExeTest
{
    //通过检测Mutex,确认只会启用一个进程
    //第一个进程,会启用Tcp监听,接收参数
    //后续进程,通过TcpChannel,将参数传递给第一个进程
    //使用前,必须先调用InitSingleton,使用后必须调用UninitSingleton
    class SingletonExeController : MarshalByRefObject
    {
        private static Mutex m_Mutex = null;
        private static TcpChannel m_TCPChannel = null;
        
        //初始化
        public static void InitSingleton()
        {
            string assemblyName = System.Reflection.Assembly.GetExecutingAssembly().GetName(false).CodeBase;
            string uniqueIdentifier = assemblyName.Replace("\\", "_");
            m_Mutex = new Mutex(false, uniqueIdentifier);
        }

        //回收资源
        public static void UninitSingleton()
        {
            if (m_Mutex != null)
            {
                m_Mutex.Close();
            }
            m_Mutex = null;

            if (m_TCPChannel != null)
            {
                m_TCPChannel.StopListening(null);
            }
            m_TCPChannel = null;
        }

        //判断是否为第一个进程
        public static bool FirstProcToRun(int tcpPort,String serviceName)
        {
            if (m_Mutex.WaitOne(1, true))
            {
                CreateTCPChannel(tcpPort,serviceName);
                return true;
            }
            else
            {
                m_Mutex.Close();
                m_Mutex = null;
                return false;
            }
        }

        //创建TCP监听
        private static void CreateTCPChannel(int tcpPort,String serviceName)
        {
            try
            {
                m_TCPChannel = new TcpChannel(tcpPort);
                ChannelServices.RegisterChannel(m_TCPChannel, false);
                RemotingConfiguration.RegisterWellKnownServiceType(typeof(SingletonExeController), serviceName, WellKnownObjectMode.SingleCall);
            }
            catch(Exception ex)
            {
                //Fix me...
                //port in use
                MessageBox.Show(ex.Message);
            }
        }

        //后续进程,向第一个进程发送自己的参数
        public static void Send(int port,String serviceName, string[] s)
        {
            try
            {
                SingletonExeController ctrl;
                TcpChannel channel = new TcpChannel();
                ChannelServices.RegisterChannel(channel, false);
                try
                {
                    String address = "tcp://localhost:" + port + "/" + serviceName;
                    ctrl = (SingletonExeController)Activator.GetObject(typeof(SingletonExeController), address);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Exception: " + e.Message);
                    throw;
                }
                ctrl.Receive(s);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        //第一个进程,接收传入参数
        public void Receive(string[] s)
        {
            //Do something here
            //...

            //Test Code
            MessageBox.Show(s[0]);
        }

        //查找第一个进程
        public static Process findMainProcess()
        {
            Process currentProcess = Process.GetCurrentProcess();
            string processName = currentProcess.ProcessName;

            Process mainProcess = null;
            Process[] allProcesses = Process.GetProcessesByName(processName);
            if (allProcesses != null)
            {
                foreach (Process p in allProcesses)
                {
                    if (p.Id != currentProcess.Id)
                    {
                        if (p.MainWindowHandle != null)
                        {
                            mainProcess = p;
                            break;
                        }
                    }
                }
            }

            return mainProcess;
        }

        //查找第一个进程的主窗口
        public static IntPtr findMainWnd()
        {
            IntPtr mainWnd = IntPtr.Zero;
            Process p = findMainProcess();
            if(p!=null && p.MainWindowHandle != null)
            {
                mainWnd=p.MainWindowHandle;
            }

            return mainWnd;
        }
    }
}

2、Program.cs

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;

namespace SingletonExeTest
{
    static class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            //Debugger.Launch();
            //Debugger.Break();

            int tcpPort = 9999;
            String serviceName = "MyTestService";

            SingletonExeController.InitSingleton();

            if (SingletonExeController.FirstProcToRun(tcpPort, serviceName))
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);

                //Do something here
                //...

                //Test Code
                Application.Run(new MainForm());
            }
            else
            {
                IntPtr mainWnd = SingletonExeController.findMainWnd();
                Win32Utils.ShowWindow(mainWnd, Win32Utils.SW_RESTORE);
                //Real Code
                //SingletonExeController.Send(tcpPort, serviceName, args);

                //Test Code
                String[] msgs = {"hi","hello","good"};
                SingletonExeController.Send(tcpPort, serviceName, msgs);
            }

            SingletonExeController.UninitSingleton();
        }
    }
}

2014版MAC分区失败

最近帮朋友在新买的MBA上分区安装widows,但无论是bootcamp还是磁盘管理工具,都提示无法分区。
用磁盘管理工具直接分区的时候,提示“不允许此Core Storage操作在稀疏逻辑宗卷组上进行”。

不知道为什么,打电话问了Apple的客服,发现是默认开启了“FileVault”功能,压力山大。
到选项-》安全与隐私-》FileVault里关掉就可以了(FileVault要加密完毕后,才能关闭,所以现在用的是虚拟机)。

鄙视Apple,一点儿提示都没有,不就是SSD盘吗,有啥了不起的,哼。

另外,这台新版MBA,重启后按option,没有Recovery选项,客服小妹妹说新版MBA要按住command+r才有这个选项。
压力山大。

这台电脑是定制的i7+8G+128G的定制版本,不知道是不是MAC OS安装时是否和普通版本是一样的,还是客服小妹妹在忽悠我啊。

R从文本文件读取矩阵

1、数据文件
1.1、InA.txt

1,2,3
4,5,6
7,8,9

1.2、InB.txt

1
2
3
4
5
6
7
8
9

1.3、InC.csv

col1,col2,col3
1,2,3
4,5,6
7,8,9

3、数据读取
3.1读行取文本转为矩阵

filename="C:\\TestData\\InA.txt"
matrixA <- as.matrix(read.table(filename, header=FALSE, sep = ",",as.is=TRUE))

3.2按Cell读取文本转为矩阵

filename="C:\\TestData\\InB.txt"
matrixB <- matrix(scan(filename),ncol=3,byrow=TRUE)

3.3直接读取CSV

filename="C:\\TestData\\InC.csv"
matrixC =read.csv(filename,header=FALSE)

4、数据输出
4.1输出为文本文件

filename="C:\\TestData\\resultA.txt"
write.table(resultA, file = resultA, row.names = F, quote = F)

4.2输出为CSV文件

filename="C:\\TestData\\resultB.csv"
write.csv(matrixResult,filename)

5、设置工作路径

setwd("C:\\TestData")

R语言矩阵运算

1向量
1.1定义向量

##定义向量,下面两种方式结果相同
##c(..., recursive = FALSE) 
x=1:12
x=c(1,2,3,4,5,6,7,b,9.10)

1.2向量与数字四则运算

##+-×/
x=1:12
y=10
z=x*y

1.3向量的内积

##%*% crossprod
x=1:5
y=1:5
z=x%*%y
z1=crossprod(x)
z2=crossprod(x,y)

1.4向量的外积

##x%o%y tcrossprod
x=1:5
y=1:5
z=x%o%y
z1=tcrossprod(x)
z2=tcrossprod(x,y)
z3=outer(x,y)

1.5矩阵转向量

vec<-function (x){
          t(t(as.vector(x)))
}
vech<-function (x){
          t(x&#91;lower.tri(x,diag=T)&#93;)
}
x=matrix(1:16,nrow=4,ncol=4,byrow=TRUE)
vec(x)
vech(x)
&#91;/code&#93;

1.6生成滞后序列
&#91;code lang="R"&#93;
library(fMultivar)
x=1:20
tslag(x,1:4,trim=F)
tslag(x,1:4,trim=T)
&#91;/code&#93;

<strong>2数组</strong>
2.1定义数组
[code lang="R"]
##向量转数组,按列转
##dim(x)
dim(x)=c(3,4);
##或者直接定义多维数组
x=array(1:12,dim=c(3,4))

3矩阵
3.1定义矩阵

##matrix(data=NA,nrow=1,ncol=1,byrow=FALSE,dimnames=NULL)
##data项为必要的矩阵元素,nrow为行数,ncol为列数,nrow与ncol的乘积应为矩阵元素个数,byrow项控制排列元素时是否按行进行,dimnames给定行和列的名称
x=matrix(1:16,nrow=4,ncol=4,byrow=TRUE)
##行数
nrow(x)
##列数
ncol(x)
##上三角阵
C=x
C[lower.tri(A)]=0
##下三角阵
C=x
C[upper.tri(A)]=0
##元素的行与列
row(x)
col(x)
D=x
D[row(x)<col(x)&#93;=0
D=x
D&#91;row(x)>col(x)]=0

3.2定义对角矩阵

##diag
A=c(1:5)
##对角阵
B=diag(A)
##获取对角元素
C=diag(B)
##生成单位对角阵
D=diag(5)

3.3矩阵与数字四则运算

##+-*/
A=matrix(1:9,nrow=3,ncol=3,byrow=TRUE)
B=10
C=A+B
D=A-B
E=A*B
F=A/B
##行和
rowSums(A)
apply(A,1,sum)
##行平均值
rowMeans(A)
apply(A,1,mean)
##行方差
apply(A,1,var)
##列和
colSums(A)
apply(A,2,sum)
##列平均值
colMeans(A)
apply(A,2,mean)
##列方差
apply(A,2,var)

3.4矩阵与矩阵加减法

##+-
A=matrix(1:9,nrow=3,ncol=3,byrow=TRUE)
B=matrix(10:18,nrow=3,ncol=3,byrow=TRUE)
C=A+B
D=A-B

3.5矩阵与矩阵乘法

##%*%
A=matrix(1:9,nrow=3,ncol=3,byrow=TRUE)
B=matrix(10:18,nrow=3,ncol=3,byrow=TRUE)
C=A%*%B
##t(A)%*%B;
C1=crossprod(A,B)
##A%*%t(B)
C2=tcrossprod(A,B)
##Hadamard积
D=A*A

3.6矩阵转置

##t(x)
A=matrix(1:6,nrow=2);
B=t(A)

3.7矩阵行列式

##det(x, ...)
A=matrix(1:9,nrow=3);
B=det(A)

3.8矩阵求逆

##solve
A=matrix(c(1,2,3,2,2,1,3,4,3),nrow=3,byrow=TRUE);
B=det(A)
C=solve(A)

##需要strucchange包,A'A的逆
library(strucchange)
C1=solveCrossprod(A,method="qr")
C2=solveCrossprod(A,method="chol")
C3=solveCrossprod(A,method="solve")
C4=solve(crossprod(A,A))

3.9求解线性方程

##solve
A=matrix(c(1,2,3,2,2,1,3,4,3),nrow=3,byrow=TRUE);
B=c(1,2,8)
C=solve(A,B)

##对于系数为三角阵的情况,可以用 backsolve及fowardsolve函数求解
##这一段有些错误,时间不够了,下次修复
A=matrix(1:9,3,3)
V=c(1,2,3)
B=A
B[upper.tri(B)]=0
backsolve(A,V,upper.tri=F,transpose=F)
forwardsolve(A,V,upper.tri=F,transpose=F)
##why not the same?
##something is wrong
solve(B,V)

3.10特征值及特征向量

##eigen
A=matrix(c(1,-2,2,-2,-2,4,2,4,-2),nrow=3,byrow=TRUE);
B=eigen(A)
##结果应该为对角阵
C=solve(B$vectors)%*%A%*%B$vectors

4.矩阵分解
4.1奇异值分解

##A=U%*%D%*%t(V),其中U, V是正交阵,D为对角阵,也就是矩阵A的奇异值
##svd
A=matrix(c(1,0,1,0,0,1),nrow=3,byrow=TRUE);
B=svd(A)
C=B$u%*%diag(B$d)%*%t(B$v)

4.2QR分解

##设A为m*n矩阵,如果存在m*m酉矩阵Q(即Q(H)Q=QQ(H)=I)和m*n阶梯形矩阵R,使得A=QR,那么此分解称为QR分解
##qr
A=matrix(c(1,1,1,2,-1,-1,2,-4,5),nrow=3,byrow=TRUE);
B=qr(A)
Q=qr.Q(B)
R=qr.R(B)
C=Q%*%R

4.3Schur分解

##A=USU(H),其中U是标准的正交矩阵(即满足UU(H)=I),S为上三角矩阵,并且对角线上的元素为A的特征值。
##Schur
library(Matrix);
A=matrix(c(1,1,1,2,-1,-1,2,-4,5),nrow=3,byrow=TRUE);
B=Schur(A, vectors=TRUE);
C=B$Q%*%B$T%*%t(B$Q)

4.4Cholesky分解

##对任意的正定矩阵A,存在上三角矩阵R,使A=t(R)%*%R,则称为A的Cholesky分解
##chol
A=matrix(c(4,-1,1,-1,4.25,2.75,1,2.75,3.5),nrow=3,byrow=TRUE);
B=chol(A);
C=t(B)%*%B;
##求行列式
D=prod(diag(chol(A))^2)
##求逆
E=chol2inv(chol(A))

Heart Curve

今天看了一下R语言,感觉还是很强大的,做了几个小例子,比如这几个画心形曲线的:

dat<- data.frame(t=seq(0, 2*pi, by=0.1) )
xhrt <- function(t) 16*sin(t)^3
yhrt <- function(t) 13*cos(t)-5*cos(2*t)-2*cos(3*t)-cos(4*t)
dat$y=yhrt(dat$t)
dat$x=xhrt(dat$t)
with(dat, plot(x,y, type="l"))
with(dat, polygon(x,y, col="hotpink"))
MASS::eqscplot(0:1,0:1,type="n",xlim=c(-1,1),ylim=c(-0.8,1.5))
curve(4/5*sqrt(1-x^2)+sqrt(abs(x)),from=-1,to=1,add=TRUE,col=2)
curve(4/5*-sqrt(1-x^2)+sqrt(abs(x)),from=-1,to=1,add=TRUE,col=2)

这两个的区别,主要是公式不一样,还有其他的公式,可以查看这里:
Heart Curve

还有用符号直接画的:

hearts <- expression(symbol('\251'))
plot( 0, xlim=c(0,2), ylim=c(0,2), type="n" )
text( 1, 1, hearts , col="red", cex=30 )  
plot(1, 1, pch = "♥", cex = 20, xlab = "", ylab = "", col = "red")