【发布时间】:2019-04-07 13:50:55
【问题描述】:
在 MATLAB 中是否有一种快速简便的方法来截断十进制数(例如超过 4 位)?
round() 没有帮助,它仍在四舍五入。我必须在 for 循环中使用它,所以最快的方法是值得赞赏的。
感谢您的意见。
【问题讨论】:
-
虽然这个问题有更好的答案,但这可能与Truncating variable MATLAB重复
在 MATLAB 中是否有一种快速简便的方法来截断十进制数(例如超过 4 位)?
round() 没有帮助,它仍在四舍五入。我必须在 for 循环中使用它,所以最快的方法是值得赞赏的。
感谢您的意见。
【问题讨论】:
这是一种截断小数点后d 数字的方法。
val = 1.234567;
d = 4;
val_trunc = fix(val*10^d)/10^d
结果
val_trunc =
1.2345
如果您知道val 是肯定的,那么floor() 将代替fix()。
【讨论】:
另一种选择:
x = -3.141592653;
x_trun = x - rem(x,0.0001)
x_trun =
-3.1415
感谢 gnovice 的更新。
一般来说,对于n 小数位:
x_trun = x - rem(x,10^-n)
【讨论】:
mod 更改为 rem,这应该适用于负数。
x - rem(x,10^-4) 或x - rem(x,10^-n) 可能会更容易,您在小数点后第n 位截断
如果您从要保留的最后一个小数后的小数中减去 5,则截断类似于舍入。
因此,将x 截断为n 十进制数字使用
round(x - sign(x)*.5/10^n, n)
(感谢@gnovice 注意到需要sign(x) 来处理负数。)
例如,
format long
x = 3.141592653589793;
for n = 2:5
result = round(x - sign(x)*.5/10^n, n);
disp(result)
end
给予
3.140000000000000
3.141000000000000
3.141500000000000
3.141590000000000
【讨论】:
format 设置,而不是舍入过程。您将面临与此处其他方法相同的输出,但 Luis 可能设置了 format long。
sign 以使其适用于负数:result = round(x - sign(x).*.5/10^n, n);
sign 是超级CPU 密集型的;)
当您要求最快的方法时,我已经汇总了当前在此处回答的前 3 种截断方法的快速基准。请看下面的代码。我将x 向量的大小增加为四舍五入,使用timeit 函数进行计时。
function benchie()
% Set up iteration variables
K = 17; n = 4; T = zeros(K,3);
for k = 1:K
x = rand(2^k,1);
% Define the three truncation functions
LuisRound = @() round(x - 0.5/10^n, n);
JodagFix = @() fix(x*10^n)/10^n;
InfoRem = @() x - rem(x,10^-n);
% Time each function
T(k,1) = timeit(LuisRound);
T(k,2) = timeit(JodagFix);
T(k,3) = timeit(InfoRem);
end
% Plot results
figure
plot(2.^(1:K), T); legend('LuisRound', 'JodagFix', 'InfoRem');
grid on; xlabel('number of elements in x'); ylabel('time taken');
end
结果图可以在这里看到:
根据此测试,jodag 建议的 fix 方法明显更快,因此您应该使用类似这样的方法来自定义截断函数到 n小数位:
function y = trunc(x, n)
%% Truncate matrix/scalar x to n decimal places
if nargin < 2; n = 0; end; % default to standard fix behaviour if no n given
y = fix(x*10^n)/10^n; % return value truncated to n decimal places
end
测试:
>> trunc([pi, 10.45, 1.9], 4)
>> ans = [3.1415 10.4500 1.9000]
>> trunc([pi, 10.45, 1.9], 1)
>> ans = [3.1 10.4 1.9]
【讨论】:
rem 选项领先。这是将代码中的 x 调整为 x = rand(2^k)-0.5; 以在不增加迭代次数的情况下将元素数量加倍。
rand(2^k)-0.5 在 -0.5 和 0.5 之间的方阵中?我不认为负值会影响结果......目前远离我的 MATLAB PC,因此无法重新运行检查,但可能很快。 与基准测试一样,里程可能会有所不同,这就是我提供代码的原因,以便任何人都可以根据自己的目的使用适当的数据进行测试:)
edit round 的round 函数有任何可见性,或者它是否被混淆了?可能是多了个检查,毕竟fix和rem基本上都是减法,round要检查是用什么方式送东西
rem 的性能如何在 点之后比fix 提高。当一次处理这么多内存时,它可能与操作系统中同时发生的其他事情有关。 (目前无法查看round。)
使用我的 round2 函数:
function result = round2(x,accuracy)
if nargin<2, accuracy=1; end %default accuracy 1 same as 'round'
if accuracy<=0, accuracy=1e-6; end
result=round(x/accuracy)*accuracy;
end
通常使用:round2(3.14159,0.01) 但你也可以用它来四舍五入到每个其他的倍数,例如:round2(number,2) 将四舍五入到偶数,或者round2(number,10) 等等。
【讨论】: