【问题标题】:truncate decimal numbers in matlab?在matlab中截断十进制数?
【发布时间】:2019-04-07 13:50:55
【问题描述】:

在 MATLAB 中是否有一种快速简便的方法来截断十进制数(例如超过 4 位)?

round() 没有帮助,它仍在四舍五入。我必须在 for 循环中使用它,所以最快的方法是值得赞赏的。

感谢您的意见。

【问题讨论】:

标签: matlab rounding


【解决方案1】:

这是一种截断小数点后d 数字的方法。

val = 1.234567;
d = 4;
val_trunc = fix(val*10^d)/10^d

结果

val_trunc =

   1.2345

如果您知道val 是肯定的,那么floor() 将代替fix()

【讨论】:

  • 根据我的基准(见我的回答),这是迄今为止最快的方法,+1
【解决方案2】:

另一种选择:

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 位截断
  • 谢谢,简单优雅
【解决方案3】:

如果您从要保留的最后一个小数后的小数中减去 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);
  • @gnovice 谢谢!已编辑
  • @gnovice 你不可能在之前我做了一个长凳?我打赌sign 是超级CPU 密集型的;)
【解决方案4】:

当您要求最快的方法时,我已经汇总了当前在此处回答的前 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] 

【讨论】:

  • 这个测试显示了有限的视图。如果将元素数量从 131,072 (2^17) 增加到 1,073,741,824 (2^30),您会得到不同的画面。 rem 选项领先。这是将代码中的 x 调整为 x = rand(2^k)-0.5; 以在不增加迭代次数的情况下将元素数量加倍。
  • rand(2^k)-0.5 在 -0.5 和 0.5 之间的方阵中?我不认为负值会影响结果......目前远离我的 MATLAB PC,因此无法重新运行检查,但可能很快。 与基准测试一样,里程可能会有所不同,这就是我提供代码的原因,以便任何人都可以根据自己的目的使用适当的数据进行测试:)
  • 是的,没错。我真的很感谢你包括代码。直到大数字才发生变化,我觉得这很奇怪。例如,对于 2^30 个元素,Rem 的经过时间约为 67 秒,Fix 的经过时间约为 69 秒,Round 的经过时间约为203秒!我现在可能不得不发布一个问题,说明为什么会发生这种情况。
  • 您是否对使用edit roundround 函数有任何可见性,或者它是否被混淆了?可能是多了个检查,毕竟fixrem基本上都是减法,round要检查是用什么方式送东西
  • 我更想知道rem 的性能如何在 点之后比fix 提高。当一次处理这么多内存时,它可能与操作系统中同时发生的其他事情有关。 (目前无法查看round。)
【解决方案5】:

使用我的 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) 等等。

【讨论】:

  • 这不是截断,而是四舍五入。
猜你喜欢
  • 2013-12-30
  • 2010-09-23
  • 2016-04-22
  • 1970-01-01
  • 2014-03-25
  • 1970-01-01
  • 2021-10-12
  • 2011-02-12
  • 1970-01-01
相关资源
最近更新 更多