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的整数).数字间以空格分隔. ...
随机推荐
- spring4-3-AOP-面向切面编程
AOP常用的两个用户:日志和验证.也就是程序追踪和数据验证. 直接使用代码实现,距离如下:
- 解决ImportError: libmysqlclient_r.so.16: cannot open shared object file-乾颐堂
在开发一个python项目是,需要用到mysql,但是, 安装完mysql-python后import加载模块提示以下错误: ImportError: libmysqlclient_r.so.16: ...
- 黑盒测试实践-任务进度-Day04
任务进度11-29 使用工具 selenium 小组成员 华同学.郭同学.穆同学.沈同学.覃同学.刘同学 任务进度 经过了前两天的学习任务的安排,以下是大家的任务进度: 华同学(任务1) 1.和其他小 ...
- java轻量级IOC框架Guice(转)
出处:http://www.cnblogs.com/whitewolf/p/4185908.html Guice是由Google大牛Bob lee开发的一款绝对轻量级的java IoC容器.其优势在于 ...
- [GO]goroutine的使用
package main import ( "fmt" "time" ) func NewTask() { for true { fmt.Println(&qu ...
- [operator]ELK6的安装
找了很久才找到一个博客写得比较全面的,FrankDeng 系统环境:CentOS7 相关软件:node-v10.9.0.tar.gz.kibana-6.4.0-linux-x86_64.tar.gz. ...
- Eclipse下配置主题颜色
插件地址 http://eclipse-color-theme.github.com/update 安装之后 下载安装好之后,点击window -> preferences -> Gen ...
- Java中的Type
Type是Java 编程语言中所有类型的公共高级接口(官方解释),也就是Java中所有类型的“爹”:其中,“所有类型”的描述尤为值得关注.它并不是我们平常工作中经常使用的 int.String.Lis ...
- Shell脚本中$0、$?、$!、$$、$*、$#、$@
1. $$Shell本身的PID(ProcessID) 2. $!Shell最后运行的后台Process的PID 3. $?最后运行的命令的结束代码(返回值) 4. $-使用Set命令设定的Flag一 ...
- UT源码 065
NextDate函数问题 NextDate函数说明一种复杂的关系,即输入变量之间逻辑关系的复杂性 NextDate函数包含三个变量month.day和year,函数的输出为输入日期后一天的日期. 要求 ...