精华内容
下载资源
问答
  • 浮点转定点

    千次阅读 2017-04-26 16:45:27
    浮点 定点 转换 Q12 Q16 Q8

    在DSP世界中,由于DSP芯片的限制,经常使用定点小数运算。所谓定点小数,实际上就是用整数来进行小数运算。下面先介绍定点小数的一些理论知识,然后以C语言为例,介 绍一下定点小数运算的方法。在TI C5000 DSP系列中使用16比特为最小的储存单位,所以我们就用16比特的整数来进行定点小数运算。       

         先从整数开 始,16比特的储存单位最多可以表示0x0000到0xffff,65536种状态,如果它表示C语言中的无符号整数的话,就是从0到65535。如果需 要表示负数的话,那么最高位就是符号位,而剩下的15位可以表示32768种状态。这里可以看出,对于计算机或者DSP芯片来说,符号并没有什么特殊的储 存方式,其实是和数字一起储存的。为了使得无论是无符号数还是符号数,都可以使用同样的加法减法规则,符号数中的负数用正数的补码表示。
         我们都知道 -1 + 1 =0,而0x0001表示1,那么-1用什么来表示才能使得-1 + 1 =0呢?答案很简单:0xffff。现在就可以打开Windows的计算器,用16进制计算一下0xffff+0x0001,结果是0x10000。那么 0x10000和0x0000等价麽,我们刚才说过用16比特来表达整数,最高位的1是第17位,这一位是溢出位,在运算寄存器中没有储存这一位,所以结 果是低16位,也就是0x0000。现在我们知道负数的表达方式了。举个例子:-100。首先我们需要知道100的16进制,用计算器转换一下,可以知道 是0x0064,那么-100就是0x10000 - 0x0064,用计算器算一下得0xff9c。还有一种简单的转换符号的方法,就是取反加一:把数x写成二进制格式,每位0变1,1变0,最后把结果加1 就是-x了。
         好,复习了整数的相关知识之后,我们进入定点小数运算环节。所谓定点小数,就是小数点的位置是固定的。我们是要用整 数来表示定点小数,由于小数点的位置是固定的,所以就没有必要储存它(如果储存了小数点的位置,那就是浮点数了)。既然没有储存小数点的位置,那么计算机 当然就不知道小数点的位置,所以这个小数点的位置是我们写程序的人自己需要牢记的。
         先以10进制为例。如果我们能够计算12+34=46的话,当然也就能够计算1.2+3.4 或者 0.12+0.34了。所以定点小数的加减法和整数的相同,并且和小数点的位置无关。乘法就不同了。 12*34=408,而1.2*3.4=4.08。这里1.2的小数点在第1位之前,而4.08的小数点在第2位之前,小数点发生了移动。所以在做乘法的 时候,需要对小数点的位置进行调整?!可是既然我们是做定点小数运算,那就说小数点的位置不能动!!怎么解决这个矛盾呢,那就是舍弃最低位。 也就说1.2*3.4=4.1,这样我们就得到正确的定点运算的结果了。所以在做定点小数运算的时候不仅需要牢记小数点的位置,还需要记住表达定点小数的 有效位数。上面这个例子中,有效位数为2,小数点之后有一位。
         现在进入二进制。我们的定点小数用16位二进制表达,最高位是符号位,那么有效位就是15位。小数点之后可以有0 - 15位。我们把小数点之后有n位叫做Qn,例如小数点之后有12位叫做Q12格式的定点小数,而Q0就是我们所说的整数。
         Q12的正数的最大值是 0 111.111111111111,第一个0是符号位,后面的数都是1,那么这个数是十进制的多少呢,很好运算,就是 0x7fff / 2^12 = 7.999755859375。对于Qn格式的定点小数的表达的数值就它的整数值除以2^n。在计算机中还是以整数来运算,我们把它想象成实际所表达的值 的时候,进行这个运算。
         反过来把一个实际所要表达的值x转换Qn型的定点小数的时候,就是x*2^n了。例如 0.2的Q12型定点小数为:0.2*2^12 = 819.2,由于这个数要用整数储存, 所以是819 即 0x0333。因为舍弃了小数部分,所以0x0333不是精确的0.2,实际上它是819/2^12 =0.199951171875。


    我们用数学表达式做一下总结: 
    x表示实际的数(*一个浮点数),q表示它的Qn型定点小数(一个整数)。 
         q = (int)(x * 2^n)
         x = (float)q/2^n


    由以上公式我们可以很快得出定点小数的+-*/算法: 
    假设q1,q2,q3表达的值分别为x1,x2,x3 
         q3 = q1 + q2   若 x3 = x1 + x2 
         q3 = q1 - q2   若 x3 = x1 - x2 
         q3 = q1 * q2 / 2^n若 x3 = x1 * x2 
         q3 = q1 * 2^n / q2若 x3 = x1 / x2


    我们看到加减法和一般的整数运算相同,而乘除法的时候,为了使得结果的小数点位不移动,对数 值进行了移动。 
    用c语言来写定点小数的乘法就是: 
         short q1,q2,q3; 
         ....

    展开全文
  • 本文主要介绍DSP中浮点定点概述,很值得学习一下,需要的朋友可以参考一下。
  • 一:浮点定点概述  1.1相关定义说明  定点数:通俗的说,小数点固定的数。以人民币为例,我们日常经常说到的如123.45¥,789.34¥等等,默认的情况下,小数点后面有两位小数,即角,分。如果小数点在最高有效位...
  • 浮点转定点运算

    2017-02-03 11:10:18
    浮点转定点运算 标签: numerical computatio 2016-07-24 20:39 859人阅读 评论(0) 收藏 举报  分类: numerical computation(4)
    http://blog.csdn.net/baidu_24281959/article/details/52015811 


    浮点转定点运算

    标签: numerical computatio
     859人阅读 评论(0) 收藏 举报
     分类:

    Original Source:

    http://www.cnblogs.com/s_agapo/archive/2012/03/20/2407332.html

    http://blog.csdn.net/sonictl/article/details/9018681


    原文基于信号处理,本文对原文进行了精简和勘误,主要就浮点转定点运算的思想实现进行说明:


    1. 简介:

    采用定点数进行数值运算,其操作数一般采用整型数来表示。

    一个整型数的最大表示范围取决于运算芯片所给定的字长,一般为16位或24位。

    显然,字长越长,所能表示的数的范围越大,精度也越高。如无特别说明,本文均以16位字长为例。

    参与运算的数以二进制补码形式表示。每个16位数用一个符号位来表示数的正负,0表示数值为正,1则表示数值为负。

    其余15位表示数值的大小。


    1.1 示例:
    二进制数 
    0 010000000000011 B = 8195
    二进制数 1 111111111111100 B = -4


    1.2 定点表示

    参与数值运算的数为16位的整型数。但在许多情况下,数学运算过程中的数不一定都是整数。

    应该说,运算芯片本身无法处理小数。关键就是由程序员来确定一个数的小数点处于16位中的哪一位。这就是数的定标

    {通过设定小数点在16位数中的不同位置,就可以表示不同大小和不同精度的小数}

    数的定标有Q表示法和S表示法两种。下面列出了一个16位数的16种Q表示、S表示及它们所能表示的十进制数值范围:


    Q表示      S表示         十进制数表示范围

    Q15    S0.15    -1≤x≤0.9999695
    Q14    S1.14    -2≤x≤1.9999390
    Q13    S2.13    -4≤x≤3.9998779
    Q12    S3.12    -8≤x≤7.9997559
    Q11    S4.11    -16≤x≤15.9995117
    Q10    S5.10    -32≤x≤31.9990234
    Q9     S6.9     -64≤x≤63.9980469
    Q8     S7.8     -128≤x≤127.9960938
    Q7     S8.7     -256≤x≤255.9921875
    Q6     S9.6     -512≤x≤511.9804375
    Q5     S10.5    -1024≤x≤1023.96875
    Q4     S11.4    -2048≤x≤2047.9375
    Q3     S12.3    -4096≤x≤4095.875
    Q2     S13.2    -8192≤x≤8191.75
    Q1     S14.1    -16384≤x≤16383.5
    Q0     S15.0    -32768≤x≤32767


    1.3 定点表示示例:

    同样一个16位数,若小数点设定的位置不同,它所表示的数也不同(首位为符号位):

    16进制数2000 H= 二进制数0 010 0000 0000 0000 B= 十进制数8192, Q0表示法
    16进制数 2000 H= 二进制数0 010 0000 0000 0000 B= 十进制数0.25 , Q15表示法


    2. 浮点定点转换:

    不同的Q所表示的数不仅范围不同,而且精度也不相同。

    Q越大,数值范围越小,但精度越高;相反,Q越小,数值范围越大,但精度就越低。

    E.g. 

    Q0 的数值范围是-32768+32767,其精度为1;而Q15的数值范围为-10.9999695,精度为1/32768=0.00003051

    因此,对定点数而言,数值范围与精度是一对矛盾。

    一个变量要想能够表示比较大的数值范围,必须以牺牲精度为代价;而想精度提高,则数的表示范围就相应地减小

    在实际的定点算法中,为了达到最佳的性能,必须充分考虑到这一点。


    2.2 转换关系:

    浮点数与定点数的转换关系可表示为:

    浮点数(Fx)转换为定点数(Ix):Ix = (int)x* 2^Q
    定点数(Ix)转换为浮点数(Fx):Fx= (float)Ix*2^(-Q)


    2.3 转换示例:

    浮点数 Fx = 0.5,定标 Q = 15,则定点数:

    Ix = floor(0.5*32768) = 16384

    反之,一个用 Q = 15 表示的定点数Ix = 16384,其浮点数为:

    Fx = 16384 * 2^(-15) = 16384 / 32768 = 0.5

    浮点数转换为定点数时,为了降低截尾误差,可以在取整前可以先加上0.5,视情况而定。


    3. C语言实现定点预算模拟:

    将浮点加法/减法转化为定点加法/减法时最重要的一点就是必须保证两个操作数的定标:

    若两者不一样,则在做加法/减法运算前先进行小数点的调整

    为保证运算精度,需使Q值小的数调整为与另一个数的Q值一样大

    此外,在做加法/减法运算时,必须注意结果可能会超过16位表示

    如果加法/减法的结果超出16位的表示范围,则必须保留32位结果,以保证运算的精度,否则可能会出现严重的精度丢失。


    3.1 结果不超过16位的定点加法描述:

    1. // 设x的Q值为Qx,y的Q值为Qy,且Qx > Qy,加法/减法结果z的定标值为Qz  
    2. // 所以定点加法可以描述为:  
    3. int x,y,z;  
    4. long temp; // 临时变量  
    5. temp = y << (Qx - Qy);  
    6. // Q大-Q小,Q大的变量分辨率更高,Q小的左移增加其Q  
    7. temp = x + temp;  
    8. z = (int)(temp >> (Qx - Qz)); // if Qx >= Qz   
    9. z = (int)(temp << (Qz - Qx)); // if Qx <= Qz  
    E.g.

    1. // 设x = 0.5,y = 3.1,则浮点运算结果为z = x+y = 0.5+3.1 = 3.6;  
    2. // Qx = 15,Qy = 13,Qz = 13,则定点加法为:  
    3. x = 16384;y = 25395;  
    4. temp = 25395 << 2 = 101580;  
    5. temp = x+temp = 16384+101580 = 117964;  
    6. z = (int)(117964L >> 2) = 29491;  
    7. // 因为z的Q值为13,所以定点值z = 29491即为浮点值z = 29491/8192 = 3.6。  
    More Examples.Here.

    3.2 定点乘法:

    1. int x,y,z;  
    2. long temp;  
    3. temp = (long)x;  
    4. z = (temp×y) >>(Qx+Qy-Qz);  
    E.g.

    1. // 设x = 18.4,y = 36.8,则浮点运算值为z = 18.4×36.8 = 677.12;  
    2. // 根据上节,得Qx = 10,Qy = 9,Qz = 5,所以  
    3. x = 18841;y = 18841;  
    4. temp = 18841L; // Long int  
    5. z = (18841L * 18841) >> (10+9-5) = 354983281L >> 14 = 21666;  
    6. // 因为z的定标值为5,故定点 z = 21666即为浮点的 z = 21666/32 = 677.08 产生了精度损失  

    3.3 混合表示法:

    许多情况下,运算过程中为了既满足数值的动态范围又保证一定的精度,就必须采用Q0与Q15之间的表示法。

    比如,数值1.2345,显然Q15无法表示,而若用Q0表示,则最接近它的数是1,精度无法保证。因此,数1.2345最佳的表示法是Q14。
    一般的,若一个数的整数位为 i位,小数位为 j 位,另一个数的整数位为 m 位,小数位为 n 位,则这两个数的乘积为 ( i + m ) 位整数位和 (j + n) 位小数位。这个乘积的最高16位可能的精度为( i + m )整数位和(15 - i - m)小数位。
    但是,若事先了解数的动态范围,就可以增加数的精度

    例如,程序员了解到上述乘积不会大于1.9999390,就可以用Q14数表示乘积,而不是理论上的最佳情况Q13。

    展开全文
  • 本文主要讲解DSP浮点转定点运算举例及编程中的心得 ,具有参考价值,需要的朋友可以参考一下。
  • DSP芯片浮点转顶点运算
  • 开发了一套浮点转定点自动位宽优化软件系统(SATRANS),能够将用户输入的描述目标系统的浮点程序自动转换为位宽可配置的定点程序,并基于模拟退火算法进行自动位宽搜索,以得到满足精度要求的操作数定点位宽组合。...
  • DSP功能函数-数据拷贝,数据填充和浮点转定点
    展开全文
  • 双精度浮点转定点When dealing with fixed point numbers, you have to be very careful – especially if you develop with PHP and MySQL. In this article, obstacles and subtleties of working with the ...

    双精度浮点转定点

    When dealing with fixed point numbers, you have to be very careful – especially if you develop with PHP and MySQL. In this article, obstacles and subtleties of working with the PHP BCMath extension, MySQL fixed point expression handling and persisting fixed point data from PHP to MySQL are described. Despite the occurring barriers we try to figure out how to work with fixed point numbers and not to lose a digit.

    处理定点数时,必须非常小心-特别是如果您使用PHP和MySQL开发。 在本文中,描述了使用PHP BCMath扩展,MySQL定点表达式处理以及将定点数据从PHP保留到MySQL的障碍和精妙之处。 尽管存在障碍,我们仍尝试找出如何使用定点数而不丢失数字。

    BCMath的麻烦 (Troubles with BCMath)

    BCMath documentation says:

    BCMath文档说:

    For arbitrary precision mathematics PHP offers the Binary Calculator which supports numbers of any size and precision, represented as strings.

    对于任意精度数学,PHP提供了二进制计算器,该计算器支持任意大小和精度的数字,以string表示。

    So BCMath function parameters should be represented as strings. Passing numeric values to bcmath can lead to wrong results, the same precision loss as when we treat double value as string

    因此,BCMath函数参数应表示为字符串。 将数值传递给bcmath可能会导致错误的结果,与我们将double值视为字符串时的精度损失相同

    情况1 (Case 1)

    echo bcmul(776.210000, '100', 10) . PHP_EOL;
        echo bcmul(776.211000, '100', 10) . PHP_EOL;
        echo bcmul(776.210100, '100', 10) . PHP_EOL;
    
        echo bcmul(50018850776.210000, '100', 10) . PHP_EOL;
        echo bcmul(50018850776.211000, '100', 10) . PHP_EOL;
        echo bcmul(50018850776.210100, '100', 10) . PHP_EOL;

    Results are:

    结果是:

    77621.00
        77621.100
        77621.0100
        5001885077621.00
        5001885077621.100
        5001885077621.00 //here we can see precision loss

    Never pass numeric values to BCMath functions, only string values that represent numbers. Even when not dealing with floating points, BCMath can output strange results:

    切勿将数字值传递给BCMath函数,仅将代表数字的字符串值传递给BCMath函数 。 即使不处理浮点,BCMath也会输出奇怪的结果:

    情况二 (Case 2)

    echo bcmul('10', 0.0001, 10) . PHP_EOL;
    	echo bcmul('10', 0.00001, 10) . PHP_EOL;
    	echo 10*0.00001 . PHP_EOL;

    Results are:

    结果是:

    0.0010
    	0 // thats really strange!!!
    	0.0001

    The reason for this is that BCMath converts its arguments to strings, and there are cases in which a number’s string representation has exponential notation.

    原因是BCMath将其参数转换为字符串,并且在某些情况下,数字的字符串表示形式具有指数表示法。

    情况3 (Case 3)

    echo bcmul('10', '1e-4', 10) . PHP_EOL; //outputs 0 as well

    PHP is a weakly typed language and in some cases you can’t control input in a strict way – you want to process as many requests as possible.

    PHP是一种弱类型的语言,在某些情况下,您不能严格地控制输入-您希望处理尽可能多的请求。

    For example we can “fix” Case 2 and Case 3 by applying sprintf transformation:

    例如,我们可以通过应用sprintf转换来“修复” 案例2案例3

    $val = sprintf("%.10f", '1e-5');
    	echo bcmul('10', $val, 10) . PHP_EOL;
    	// gives us 0.0001000000

    but applying the same transformation can break Case 1 “proper” behaviour:

    但是应用相同的转换可能会破坏案例1的 “适当”行为:

    $val = sprintf("%.10f", '50018850776.2100000000');
    	echo bcmul('10', $val, 10) . PHP_EOL;
    	echo bcmul('10', 50018850776.2100000000, 10) . PHP_EOL;
    	500188507762.0999908450 //WRONG
    	500188507762.10 //RIGHT

    So the sprintf solution is not suitable for BCmath. Assuming all user inputs are strings, we can implement a simple validator, catching all exponential notation numbers and converting them properly. This technique is done in php-bignumbers, so we can safely pass in arguments like 1e-20 and 50018850776.2101 without losing precision.

    因此, sprintf解决方案不适用于BCmath。 假设所有用户输入都是字符串,我们可以实现一个简单的验证器,捕获所有指数符号数并将其正确转换。 这项技术是在php-bignumbers中完成的 ,因此我们可以安全地传递1e-2050018850776.2101类的参数,而不会损失精度。

    echo bcmul("50018850776.2101", '100', 10) . PHP_EOL;
    	echo bcmul(Decimal::create("50018850776.2101"), '100', 10) . PHP_EOL;
    
    	echo bcmul(Decimal::create("1e-8"), '100', 10) . PHP_EOL;
    	echo bcmul("1e-8", '100', 10) . PHP_EOL;
    
    	echo bcmul(50018850776.2101, '100', 10) . PHP_EOL;
    	echo bcmul(Decimal::create(50018850776.2101), '100', 10) . PHP_EOL;
    	
    	// Result
    	// 5001885077621.0100
    	// 5001885077621.0100
    	// 0.00000100
    	// 0
    	// 5001885077621.00
    	// 5001885077621.00982700

    But the last two lines of the example show us that floating point caveats cannot be avoided by input parsing (which is completely logical – we can not deal with PHP internal double representation).

    但是该示例的最后两行向我们展示了输入解析无法避免浮点警告(这是完全合乎逻辑的,我们无法处理PHP内部双重表示形式)。

    BCMath最终指南 (BCMath final guidelines)

    Never use floating point numbers as fixed point operation arguments. String conversion does not help, because we can not manage the precision loss in any way.

    切勿将浮点数用作定点运算参数。 字符串转换无济于事,因为我们无法以任何方式管理精度损失。

    When using BCMath extension operations, be careful with arguments in exponential representation. BCMath functions do not process exponential arguments (i.e. ‘1e-8’) correctly, so you should convert them manually. Be careful, do not use sprintf or similar conversion techniques, because it leads to precision loss.

    使用BCMath扩展操作时,请小心使用指数表示形式的参数。 BCMath函数不能正确处理指数参数(即“ 1e-8”),因此您应该手动转换它们。 请注意,请勿使用sprintf或类似的转换技术,因为这会导致精度损失。

    You can use the php-bignumbers library which handles input arguments in exponential form and provides users with fixed point math operations functions. However, its performance is worse than that of the BCMath extension, so it’s a kind of compromise between a robust package and performance.

    您可以使用php-bignumbers库,该库以指数形式处理输入参数,并为用户提供定点数学运算功能。 但是, 它的性能比BCMath扩展的性能差 ,因此它是健壮的程序包和性能之间的一种折衷。

    MySQL和定点数 (MySQL and fixed point numbers)

    In MySQL, fixed point numbers are handled with the DECIMAL column type. You can read the official MySQL documentation for data types and precision math operations.

    在MySQL中,定点数使用DECIMAL列类型处理。 您可以阅读MySQL官方文档,了解数据类型精确数学运算

    The most interesting part is how MySQL handles expressions:

    最有趣的部分是MySQL如何处理表达式:

    Handling of a numeric expression depends on the kind of values the expression contains:

    数值表达式的处理取决于表达式包含的值的类型:

    If any approximate values are present, the expression is approximate and is evaluated using floating-point arithmetic.

    如果存在任何近似值,则该表达式为近似值,并使用浮点算法对其求值。

    If no approximate values are present, the expression contains only exact values. If any exact value contains a fractional part (a value following the decimal point), the expression is evaluated using DECIMAL exact arithmetic and has a precision of 65 digits. The term “exact” is subject to the limits of what can be represented in binary. For example, 1.0/3.0 can be approximated in decimal notation as .333…, but not written as an exact number, so (1.0/3.0)*3.0 does not evaluate to exactly 1.0.

    如果没有近似值,则表达式仅包含精确值。 如果任何精确值包含小数部分(小数点后的值),则使用DECIMAL精确算术对表达式求值,并且精度为65位数。 术语“精确”受可以用二进制表示的限制。 例如,可以用十进制表示法将1.0 / 3.0近似为.333…,但不能写为确切数字,因此(1.0 / 3.0)* 3.0的取值不能精确为1.0。

    Otherwise, the expression contains only integer values. The expression is exact and is evaluated using integer arithmetic and has a precision the same as BIGINT (64 bits).

    否则,表达式仅包含整数值。 该表达式是精确的,并且使用整数算术求值,并且精度与BIGINT(64位)相同。

    If a numeric expression contains any strings, they are converted to double-precision floating-point values and the expression is approximate.

    如果数字表达式包含任何字符串,则将它们转换为双精度浮点值,并且该表达式为近似值。

    Here is a short example that demonstrates fractional part cases:

    这是一个简短的示例,展示了部分案例:

    mysql> CREATE TABLE fixed_point (
            ->   amount NUMERIC(40,20) NOT NULL
            -> ) engine=InnoDB, charset=utf8;
        Query OK, 0 rows affected (0.02 sec)
    
        mysql> INSERT INTO fixed_point (amount) VALUES(0.2);
        Query OK, 1 row affected (0.00 sec)
    
        mysql> SELECT amount, amount + 0.1, amount + 1e-1, amount + '0.1' FROM fixed_point;
        +------------------------+------------------------+---------------------+---------------------+
        | amount                 | amount + 0.1           | amount + 1e-1       | amount + '0.1'      |
        +------------------------+------------------------+---------------------+---------------------+
        | 0.20000000000000000000 | 0.30000000000000000000 | 0.30000000000000004 | 0.30000000000000004 |
        +------------------------+------------------------+---------------------+---------------------+
        1 row in set (0.00 sec)

    It may seen quite straightforward, but let’s look at how to deal with it within PHP.

    它看起来很简单,但是让我们看一下如何在PHP中处理它。

    PHP和MySQL中的精确数学 (Precision math in PHP & MySQL)

    So now we have to persist our fixed point values from PHP into MySQL. The right way is to use prepared statements and placeholders within our queries. Then we do parameter binding and everything is safe and secure.

    因此,现在我们必须将定点值从PHP保留到MySQL中。 正确的方法是在查询中使用准备好的语句和占位符。 然后我们进行参数绑定,一切都是安全的。

    $amount_to_add = "0.01";
    	$stmt = $dbh->prepare("UPDATE fixed_point SET amount = amount + :amount");
    	$stmt->bindValue("amount", $amount_to_add);
    	$stmt->execute();

    When we bind a value to a statement placeholder, we can specify its type by the bindValue third argument. Possible types are represented by constants PDO::PARAM_BOOL, PDO::PARAM_NULL, PDO::PARAM_INT, PDO::PARAM_STR, PDO::PARAM_LOB and PDO::PARAM_STMT. So the problem is that the PHP PDO extension does not have a decimal parameter type for binding. As a result, all math expressions in queries are treated as floating point expressions, not as fixed point expressions.

    当我们将值绑定到语句占位符时,可以通过bindValue第三个参数指定其类型。 可能的类型由常量PDO::PARAM_BOOLPDO::PARAM_NULLPDO::PARAM_INTPDO::PARAM_STRPDO::PARAM_LOBPDO::PARAM_STMT 。 因此,问题在于PHP PDO扩展名没有用于绑定的十进制参数类型。 结果,查询中的所有数学表达式都被视为浮点表达式,而不是定点表达式。

    $dbh = new PDO("mysql:host=localhost;dbname=test", "root", "");
        $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $sql = "
            CREATE TABLE IF NOT EXISTS fixed_point (
                amount DECIMAL(43,20)
            )
        ";
        $dbh->query($sql);
    
        $dbh->query("DELETE FROM fixed_point");
        $dbh->query("INSERT INTO fixed_point VALUES(0.2)");
    
        $amount_to_add = "0.1";
        $stmt = $dbh->prepare("UPDATE fixed_point SET amount = amount + :amount");
        $stmt->bindValue("amount", $amount_to_add);
        $stmt->execute();
    
        $stmt = $dbh->prepare("SELECT amount FROM fixed_point");
        $stmt->execute();
        var_dump($stmt->fetchColumn());
    
        //output is string(22) "0.30000000000000004000"

    If we want to take the advantage of prepared statements and work with fixed point numbers, the best way is to perform all math operations in PHP and save results to MySQL.

    如果我们想利用准备好的语句的优势并使用定点数,最好的方法是在PHP中执行所有数学运算并将结果保存到MySQL。

    $amount_to_add = "0.1";
    	$stmt = $dbh->prepare("SELECT amount FROM fixed_point");
    	$stmt->execute();
    	$amount = $stmt->fetchColumn();
    	$new_amount = bcadd($amount, $amount_to_add, 20);
    	$stmt = $dbh->prepare("UPDATE fixed_point SET amount=:amount");
    	$stmt->bindValue("amount", $new_amount);
    	$stmt->execute();
    	$stmt = $dbh->prepare("SELECT amount FROM fixed_point");
    	$stmt->execute();
    	$amount_after_change = $stmt->fetchColumn();
    	echo $amount_after_change . PHP_EOL;

    结论 (Conclusion)

    We’ve reached the following conclusions:

    我们得出以下结论:

    • Never use floating point numbers as fixed point operations arguments in BCMath PHP extension funcitons. Only strings.

      切勿在BCMath PHP扩展功能中将浮点数用作定点运算参数。 仅字符串。
    • BCMath extension does not work with string numbers in exponential representation

      BCMath扩展不适用于指数表示形式的字符串
    • MySQL supports fixed point number expressions, but all operands have to be in decimal format. If at least one agrument is in exponential format or string, it is treated as floating point number and the expression is evaluated as floating point number.

      MySQL支持定点数表达式,但是所有操作数必须为十进制格式。 如果至少一个agru的形式为指数格式或字符串,则将其视为浮点数,并将表达式评估为浮点数。
    • PHP PDO extension does not have Decimal parameter type, so if you use prepared statements and binding parameters in SQL expressions that contain fixed point operands – you won’t get precise results.

      PHP PDO扩展名没有Decimal参数类型,因此,如果在包含定点操作数SQL表达式中使用准备好的语句和绑定参数,则不会得到精确的结果。

    • To perform precise math operations in PHP+MySQL applications you can choose two ways. The first one is to process all operations in PHP and persist data to MySQL only with INSERT or UPDATE statements. In this case you can use prepared statements and parameter binding. The second one is to build SQL queries manually (you can still use prepared statements, but you have to escape parameters by yourself) so all SQL math expressions are in decimal number representation.

      要在PHP + MySQL应用程序中执行精确的数学运算,可以选择两种方法。 第一个是处理PHP中的所有操作,并且仅使用INSERTUPDATE语句将数据持久保存到MySQL。 在这种情况下,您可以使用准备好的语句和参数绑定。 第二个方法是手动构建SQL查询(您仍然可以使用准备好的语句,但必须自己转义参数),以便所有SQL数学表达式均以十进制数表示。

    My personal favorite approach is the first one: all math operations in PHP. I agree that PHP and MySQL may be not the best choice for applications with precision math, but if you chose this technology stack, it’s good to know that there is a way to deal with it the right way.

    我个人最喜欢的方法是第一个:PHP中的所有数学运算。 我同意PHP和MySQL可能不是精确数学应用程序的最佳选择,但是如果您选择了此技术堆栈,那么很高兴知道有一种方法可以正确处理它。

    翻译自: https://www.sitepoint.com/fixed-point-math-php-bcmath-precision-loss-cases/

    双精度浮点转定点

    展开全文
  • 本人正在学习浮点定点转化,查阅了好多资源,包括硕士论文,其中讲解大都泛泛,并不适合初学者,而该文档是唯一让我眼前一亮的好文档。原理讲述特别清楚。
  • 3.定点数的加减乘除运算 ...代码的意思是,该模块需要输出一个整型的结果,但计算的过程中有浮点的运算。如果在定点的DSP中,这段代码是无法运行的。 为了解决这个问题,我们可以这样处理:首先,把coefs1,coefs2等类
  • 4.定点数模拟浮点数运算及常见的策略  相信大家到现在已经大致明白了浮点数转换成定点数运算的概貌。其实,原理讲起来很简单,真正应用到实际的项目中,可能会遇到各种各样的问题。具我的经验,常见的策略有如下几...
  • 转载一些 浮点转定点运算的帖子

    千次阅读 2013-03-08 10:46:15
    与afreez一起学习DSP中浮点转定点运算 http://blog.csdn.net/ganxingming/article/details/1449526 ------------------------------------------------------------------------------------------------ 这...
  • 本文主要介绍DSP中定点数的加减乘除运算,很值得学习一下,需要的朋友可以参考一下。
  • 第16章 DSP功能函数-数据拷贝,数据填充和浮点转定点 本期教程主要讲解功能函数中的数据拷贝,数据填充和浮点数转换为定点数。 目录 第16章 DSP功能函数-数据拷贝,数据填充和浮点转定点 16.1 初学者重要提示 ...
  • #defineMIN(X,Y)(X>.../**浮点的加法运算转换为定点的加法运算 *author:zgr2014-04-03 *1.内存中符号位+阶码+尾数的浮点表示法转换为符号位+整数部分+尾数部分的表示法 *2.找到合适的Q值,并取较大的...
  • DSP定点算数运算1数的定标在定点DSP芯片中,采用定点数进行数值运算,其操作数一般采用整型数来表示。一个整型数的最大表示范围取决于DSP芯片所给定的字长,一般为16位或24位。显然,字长越长,所能表示的数的范围越大...
  • 第16章 DSP功能函数-数据拷贝,数据填充和浮点转定点 本期教程主要讲解功能函数中的数据拷贝,数据填充和浮点数转换为定点数。 目录 第16章 DSP功能函数-数据拷贝,数据填充和浮点转定点 16.1 初学者重要提示 ...
  • 第16章 DSP功能函数-数据拷贝,数据填充和浮点转定点 本期教程主要讲解功能函数中的数据拷贝,数据填充和浮点数转换为定点数。 目录 第16章 DSP功能函数-数据拷贝,数据填充和浮点转定点 16.1 初学者重要提示 ...
  • 二:浮点数的存储格式 2.1 IEEE floating point standard  上面我们说了,浮点数的小数点是不固定的,如果每个人都按照自己的爱好存储在电脑里,那不就乱套了吗?那么怎么在计算机中存储这种类型的数字呢?...
  •  “第3章 DSP芯片的定点运算.doc”这篇文章中给了一个很简单有能说明问题的例子,不想动大脑了,直接引用过来如下。  这是一个对语音信号(0.3kHz~3.4kHz)进行低通滤波的C语言程序,低通滤波的截止频率为800Hz,...
  • 本文主要讲解DSP中定点数模拟浮点数运算及常见的策略,具有参考价值,需要的朋友可以参考一下。
  • 本文主要介绍DSP中浮点数的存储格式,很值得学习一下,需要的朋友可以参考一下。
  • IQMath是什么 浮点转定点运算,dsp

    千次阅读 2018-01-22 14:02:00
    【转帖注明出处:blog.csdn.net/lanmanck】 网上搜了一下没发现非常合适的,特写出来与大家分享。...有人就想到了,把浮点转定点就能够了。好了IQmath就是干这个事的。 举个样例。有个数为0.2,...

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 325
精华内容 130
关键字:

浮点转定点