php 的加法
无意间看到了php中关于加,减,乘,除 的计算方法
http://lxr.php.net/source/xref/PHP-5.6/Zend/zend_operators.h#596
static zend_always_inline int fast_add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
{
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
#if defined(__GNUC__) && defined(__i386__)
__asm__(
"movl (%1), %%eax\n\t"
"addl (%2), %%eax\n\t"
"jo 0f\n\t"
"movl %%eax, (%0)\n\t"
"movb %3, %c5(%0)\n\t"
"jmp 1f\n"
"0:\n\t"
"fildl (%1)\n\t"
"fildl (%2)\n\t"
"faddp %%st, %%st(1)\n\t"
"movb %4, %c5(%0)\n\t"
"fstpl (%0)\n"
"1:"
:
: "r"(&result->value),
"r"(&op1->value),
"r"(&op2->value),
"n"(IS_LONG),
"n"(IS_DOUBLE),
"n"(ZVAL_OFFSETOF_TYPE)
: "eax","cc");
#elif defined(__GNUC__) && defined(__x86_64__)
__asm__(
"movq (%1), %%rax\n\t"
"addq (%2), %%rax\n\t"
"jo 0f\n\t"
"movq %%rax, (%0)\n\t"
"movb %3, %c5(%0)\n\t"
"jmp 1f\n"
"0:\n\t"
"fildq (%1)\n\t"
"fildq (%2)\n\t"
"faddp %%st, %%st(1)\n\t"
"movb %4, %c5(%0)\n\t"
"fstpl (%0)\n"
"1:"
:
: "r"(&result->value),
"r"(&op1->value),
"r"(&op2->value),
"n"(IS_LONG),
"n"(IS_DOUBLE),
"n"(ZVAL_OFFSETOF_TYPE)
: "rax","cc");
#else
/*
648 * 'result' may alias with op1 or op2, so we need to
649 * ensure that 'result' is not updated until after we
650 * have read the values of op1 and op2.
651 */ if (UNEXPECTED((Z_LVAL_P(op1) & LONG_SIGN_MASK) == (Z_LVAL_P(op2) & LONG_SIGN_MASK)
&& (Z_LVAL_P(op1) & LONG_SIGN_MASK) != ((Z_LVAL_P(op1) + Z_LVAL_P(op2)) & LONG_SIGN_MASK))) {
Z_DVAL_P(result) = (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2);
Z_TYPE_P(result) = IS_DOUBLE;
} else {
Z_LVAL_P(result) = Z_LVAL_P(op1) + Z_LVAL_P(op2);
Z_TYPE_P(result) = IS_LONG;
}
#endif
return SUCCESS;
} else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
Z_DVAL_P(result) = ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2);
Z_TYPE_P(result) = IS_DOUBLE;
return SUCCESS;
}
} else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
Z_DVAL_P(result) = Z_DVAL_P(op1) + Z_DVAL_P(op2);
Z_TYPE_P(result) = IS_DOUBLE;
return SUCCESS;
} else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
Z_DVAL_P(result) = Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2));
Z_TYPE_P(result) = IS_DOUBLE;
return SUCCESS;
}
}
return add_function(result, op1, op2 TSRMLS_CC);
}
其中第653行中的宏 LONG_SIGN_MASK 定义为
#define LONG_SIGN_MASK (1L << (8*sizeof(long)-1))
在64位机下,LONG_SIGN_MASK的值为 1L<< (8*8-1) = 1L<<63 = 2^63次方
Intel IA32 浮点运算
IA32处理器和很多其它一些处理器一样,有专门用于保存浮点数的寄存器,当在cpu中进行浮点数运算时,这些寄存器就用来保存输入输出及相关的中间结果。
但IA32有一个比较特别的地方,它的浮点数寄存器是80位的,而我们在程序中只用到32和64位两种类型,因此当把float,double放入到cpu中时,它们都会先被转换成了80位,然后以80位的方式进行运算,最后得到的结果再转换回来。这样特性使得浮点数的计算可以相对更精确些,但同时,一不小心很可能也会引出一些意想不到的问题。
你可能突然恍然大悟了,对的,我们最开始提到那个奇怪的问题就与此相关。
s/e得到结果是个80位的浮点数,由这个浮点数先转换成double再转成int,与直接就转换成int,结果很可能是不同的。
比如在我们的例子中,s/e ~ 29.999999....时,s/e转换成double使用round-to-even的方式,会得到也许是30.0000001,再转成整形时,得到30.
但如果直接由29.99999...转换成整型,得到却是29。
后来新出的系列Intel处理器,包括IA32及64位的处理器,提供了专门的硬件来直接处理浮点数,使得可以分开对待float型与double型,这些硬件特性在compiler的支持下,可以生相对高效的代码,同时也避免了我们上面所遇到的问题,有兴趣的读者可以google一下相关的关键字:sse。
在64位机下
int 4个字节
long 8个字节
double 8个字节
float 4个字节
double long 8个字节
指针 8个字节
而在32位机下
int 4个字节
long 4个字节
double 8个字节
float 4个字节
double long 8个字节
指针 4个字节
php 的加法的更多相关文章
- 用CIL写程序:写个函数做加法
前言: 上一篇文章小匹夫为CIL正名的篇幅比较多,反而忽略了写那篇文章初衷--即通过写CIL代码来熟悉它,了解它.那么既然有上一篇文章做基础(炮灰),想必各位对CIL的存在也就释然了,兴许也燃起了一点 ...
- [CodeWars][JS]实现大整数加法
问题描述 实现‘字符串加法’,即将两个以字符串形式表示的数字相加,得到结果然后返回一个新的字符串. 例如:输入‘123’,‘321’,返回‘444’. 这样在进行两个任意大的整数相加的时候,既不会溢出 ...
- 52. 不用+、-、×、÷做加法[add two numbers without arithmetic]
[本文链接] http://www.cnblogs.com/hellogiser/p/add-two-numbers-without-arithmetic.html [题目] 写一个函数,求两个整数的 ...
- jQuery的加法运算.
jQuery的加法运算. 加法运算 ?想必大家听到这都会不屑了,加法运算这是多么简单的运算.然而有的时候在jQuery也让人挺头疼的. 常规的是: var num1 = 123; var num2=1 ...
- 51nod 1005 大数加法
#include<iostream> #include<string> using namespace std; #define MAXN 10001 },b[MAXN]={} ...
- c++加法高精度算法
c++高精度算法,对于新手来说还是一大挑战,只要克服它,你就开启了编程的新篇章,算法. 我发的这个代码并不是很好,占用内存很多而且运行时间很长(不超过1秒),但是很好理解,很适合新手 高精算法的本质就 ...
- iOS学习——制作一个小型加法计算器
一.项目要求:制作一个加法计算器.在第1个和第2个文本框中输入两个整数,然后点击“计算”按钮,可将计算结果显示在第3个文本框中. 二.开发步骤: 1.搭建UI界面 2.监听按钮的点击事件 3.获取文本 ...
- 程序设计入门——C语言 第7周编程练习 1多项式加法(5分)
第7周编程练习 依照学术诚信条款,我保证此作业是本人独立完成的. 温馨提示: 1.本次作业属于Online Judge题目,提交后由系统即时判分. 2.学生可以在作业截止时间之前不限次数提交答案,系统 ...
- c#大数加法
在C#中,我们经常需要表示整数.但是,c#的基本数据类型中,最大的long也只能表示-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807之间的数 ...
- PAT 02-线性结构2 一元多项式的乘法与加法运算 (20分)
设计函数分别求两个一元多项式的乘积与和. 输入格式: 输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数).数字间以空格分隔. ...
随机推荐
- js-判断字符串中是否存在emoji表情
function isEmojiCharacter(substring) { for(var i = 0; i < substring.length; i++) { var hs = subst ...
- Lunix7 开放指定端口
systemctl unmask firewalld.service 此时可以正常启动Firewall了. 接下来顺便讲述一下Firewall的安装,及一些简单配置. 查看状态,看电脑上是否已经安 ...
- cs api 之一
无法创建 无法创建网络 执行顺序
- cs4.1 编译与安装
cs4.1编译报 https://issues.apache.org/jira/browse/CLOUDSTACK-2913 cs4.1安装报
- activeMQ集群搭建及高可用
三台服务器搭建如下的集群,达到了高可用.也同时达到了负载的目的: /****************************************************************** ...
- Solidity oraclize解析Json格式数据
solidity虽然不能解析json数据但是oraclize_query可以直接处理: pragma solidity ^; import "github.com/oraclize/ethe ...
- ubuntu如何安装samba
1.samba安装sudo apt-get install samba2.修改smb.confsudo gedit /etc/samba/smb.conf 文件最后增加如下代码:[share] pat ...
- HUST软工1501-1503班第4周作业成绩公布
说明 本次公布的成绩为第四周作业的结果: 第4周小组作业:WordCount优化 如果同学对作业结果存在异议,可以: 在毕博平台讨论区的第4周在线答疑区发帖申诉. 或直接在博客园本帖中进行评论进行申诉 ...
- mongodb ---- findAndModify 写法
db.coll.findAndModify({ query:{x:"ggg"}, update:{$set:{"x":"gggg"}}, f ...
- access函数使用
调用open函数时,是以有效用户而不是实际用户的身份去验证进程对要打开的文件的读写权限.但是有时候我们想知道的是实际用户而非有效用户对某一文件的权限,此时就要用到access函数. 函数原型:in ...