我正在开发一个项目,其中包含计算正弦波作为控制环路的输入。
\n正弦波的频率为 280 Hz,控制循环每 30\xc2\xa0\xc2\xb5s 运行一次,并且针对 Arm Cortex-M7 的所有内容都是用 C 编写的。
\n目前我们只是在做:
\ndouble time;\nvoid control_loop() {\n time += 30e-6;\n double sine = sin(2 * M_PI * 280 * time);\n ...\n}\nRun Code Online (Sandbox Code Playgroud)\n出现两个问题:
\n\n我有一些客户收到奇怪的账单.我能够找出核心问题:
SELECT 199.96 - (0.0 * FLOOR(CAST(1.0 AS DECIMAL(19, 4)) * CAST(199.96 AS DECIMAL(19, 4)))) -- 200 what the?
SELECT 199.96 - (0.0 * FLOOR(1.0 * CAST(199.96 AS DECIMAL(19, 4)))) -- 199.96
SELECT 199.96 - (0.0 * FLOOR(CAST(1.0 AS DECIMAL(19, 4)) * 199.96)) -- 199.96
SELECT 199.96 - (CAST(0.0 AS DECIMAL(19, 4)) * FLOOR(CAST(1.0 AS DECIMAL(19, 4)) * CAST(199.96 AS DECIMAL(19, 4)))) -- 199.96
SELECT 199.96 - (CAST(0.0 AS DECIMAL(19, 4)) * FLOOR(1.0 * CAST(199.96 AS DECIMAL(19, 4)))) -- 199.96 …Run Code Online (Sandbox Code Playgroud) $a = '35';
$b = '-34.99';
echo ($a + $b);
Run Code Online (Sandbox Code Playgroud)
结果在0.009999999999998
怎么了?我想知道为什么我的程序会报告奇怪的结果.
为什么PHP没有返回预期的0.01?
这个问题产生于我在进一步调查这个问题后发现的一些奇怪的事情......
我总是将MATLAB变量理解为默认的双精度.所以,如果我要做一些事情,比如声明一个小数点后20位数的变量:
>> num = 2.71828182845904553488;
>> class(num) % Display the variable type
ans =
double
Run Code Online (Sandbox Code Playgroud)
我希望忽略最后4位数,因为浮点相对精度大约为10 -16:
>> eps(num)
ans =
4.440892098500626e-016
Run Code Online (Sandbox Code Playgroud)
如果我尝试在小数点后面显示超过16位的数字(使用fprintf或者sprintf),我得到的结果是:
>> fprintf('%0.20f\n', num)
2.71828182845904550000
>> sprintf('%0.20f', num)
ans =
2.71828182845904550000
Run Code Online (Sandbox Code Playgroud)
换句话说,数字17到20都是0.
但是,事情变得奇怪,当我传球num给可变精度算术函数的符号工具箱,告诉它表示使用的精度21个的位数:
>> vpa(num, 21)
ans =
2.71828182845904553488
Run Code Online (Sandbox Code Playgroud)
什么?!最后4位数字再次出现!当我输入的原始数字存储为双精度变量时,它们是否应该丢失num?既然num传递给它是一个双精度变量vpa,怎么vpa知道它们是什么?
我最好的猜测是,MATLAB内部表示的num精度高于双精度,因为我将它初始化为一个数字,其数字超过小数点,而不是双精度变量可以处理的数字.这真的是发生了什么,还是正在发生的事情?
奖励:如果你还没有上述的偏头痛,这里还有另外一个混乱的根源......
>> num = 2.71828182845904553488; % Declare …Run Code Online (Sandbox Code Playgroud) 我知道浮点数是如何表示的,但是还不够,我害怕.
一般问题是:
对于给定的精度(对于我的目的,基数10中的精确小数位数),可以为16位,32位和64位IEEE-754系统表示什么范围的数字?
具体来说,我只对16位和32位数字的范围感兴趣,精确到+/- 0.5(那些位置)或+/- 0.0005(千分位数).
我正在编写一个程序,我需要删除存储在矩阵中的重复点.问题在于,当检查这些点是否在矩阵中时,MATLAB不能在矩阵中识别它们,尽管它们存在.
在以下代码中,intersections函数获取交集点:
[points(:,1), points(:,2)] = intersections(...
obj.modifiedVGVertices(1,:), obj.modifiedVGVertices(2,:), ...
[vertex1(1) vertex2(1)], [vertex1(2) vertex2(2)]);
Run Code Online (Sandbox Code Playgroud)
结果:
>> points
points =
12.0000 15.0000
33.0000 24.0000
33.0000 24.0000
>> vertex1
vertex1 =
12
15
>> vertex2
vertex2 =
33
24
Run Code Online (Sandbox Code Playgroud)
应从结果中消除两点(vertex1和vertex2).它应该通过以下命令完成:
points = points((points(:,1) ~= vertex1(1)) | (points(:,2) ~= vertex1(2)), :);
points = points((points(:,1) ~= vertex2(1)) | (points(:,2) ~= vertex2(2)), :);
Run Code Online (Sandbox Code Playgroud)
在这之后,我们有了这个意想不到的结果:
>> points
points =
33.0000 24.0000
Run Code Online (Sandbox Code Playgroud)
结果应该是一个空矩阵.如你所见,第一对(或第二对)[33.0000 24.0000]已被淘汰,但不是第二对.
然后我检查了这两个表达式:
>> points(1) ~= vertex2(1)
ans …Run Code Online (Sandbox Code Playgroud) 这不是一个问题,因为它更多的是意识到.我更新了一个json_encode()用于PHP7.1.1 的应用程序,我看到一个问题,浮动被更改为有时延伸出17位数.根据文档,serialize_precision在编码double值时,PHP 7.1.x开始使用而不是精度.我猜这导致了一个示例值
472.185
成为
472.18500000000006
在那个价值经历之后json_encode().自从我发现以来,我已经恢复到PHP 7.0.16并且我不再有问题了json_encode().我还尝试在恢复到PHP 7.0.16之前更新到PHP 7.1.2.
这个问题背后的原因确实源于PHP - 浮点数精度,但最终所有原因都是因为从精度到serialize_precision使用的变化json_encode().
如果有人知道这个问题的解决方案,我会非常乐意听取推理/修复.
摘自多维数组(之前):
[staticYaxisInfo] => Array
(
[17] => stdClass Object
(
[variable_id] => 17
[static] => 1
[min] => 0
[max] => 472.185
[locked_static] => 1
)
)
Run Code Online (Sandbox Code Playgroud)
经过json_encode()......之后
"staticYaxisInfo":
{
"17":
{
"variable_id": "17",
"static": "1",
"min": 0,
"max": 472.18500000000006,
"locked_static": "1"
}
},
Run Code Online (Sandbox Code Playgroud) C#中的这些行
decimal a = 2m;
decimal b = 2.0m;
decimal c = 2.00000000m;
decimal d = 2.000000000000000000000000000m;
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
Console.WriteLine(d);
Run Code Online (Sandbox Code Playgroud)
生成此输出:
2
2.0
2.00000000
2.000000000000000000000000000
Run Code Online (Sandbox Code Playgroud)
所以我可以看到从文字中创建一个十进制变量允许我控制精度.
我在C中有这个代码,我已经宣布0.1为double.
#include <stdio.h>
int main() {
double a = 0.1;
printf("a is %0.56f\n", a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这就是它的印刷品, a is 0.10000000000000001000000000000000000000000000000000000000
C++中的代码相同,
#include <iostream>
using namespace std;
int main() {
double a = 0.1;
printf("a is %0.56f\n", a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这就是它的印刷品, a is 0.1000000000000000055511151231257827021181583404541015625
有什么不同?当我读到两个都被分配8个字节?C++如何在小数位上打印更多数字?
另外,它怎么能到小数点55位?IEEE 754浮点只有52位的小数,我们可以得到15位十进制数的精度.它以二进制形式存储.为什么它的十进制解释存储更多?