From: bogfrog on
Hello,

I'm having an FP issue that's sort of driving me crazy. I'm doing some division by 10, subtracting, and taking a floor. Purely mathematically, this is exactly what I want to do:
------
num = 12;
a = num/10;
b = floor(a);
c = a-b;
d = 10*c;
finalResult = floor(d);
------

However, these are the results I get:

------
a = num/10 = 1.2000000000000000
b = floor(a) = 1.0000000000000000
c = a - b = 0.2000000000000000
d = 10*c = 1.9999999999999996
Final Result = floor(d) = 1.0000000000000000
------

But obviously, what I'm expecting mathematically is for the final result to be 2, not 1!

I know FP gets tricky this way... But is there anyway around this?

Basically, I'm doing this because I want to create a function that turns a number such as 3813919 into the array [3 8 1 3 9 1 9], and this was part of solving that problem (ie, decomposing a number into its digits). So if you have a good Matlab solution for that problem, that would also be a help.

I figured out an algorithm that would do this decomposition, but the FP precision screws everything up!

Thanks!


fprintf('a = num/10 = %.16f\n', a);
fprintf('b = floor(a) = %.16f\n', b);
fprintf('c = a - b = %.16f\n', c);
fprintf('d = 10*c = %.16f\n', d);
fprintf('Final Result = floor(d) = %.16f\n', finalResult);
From: Matt Fig on
Use round on the last step;
From: dpb on
bogfrog wrote:
....

> Basically, I'm doing this because I want to create a function
> that turns a number such as 3813919 into the array [3 8 1 3 9 1 9], ...

....

How about letting the i/o subsystem do it for you???

>> digits=strread(sprintf('%d',3813919),'%1d')'
digits =
3 8 1 3 9 1 9
>>

--
From: Roger Stafford on
bogfrog <aj00mcgraw(a)gmail.com> wrote in message <639153510.18073.1277346358514.JavaMail.root(a)gallium.mathforum.org>...
> Hello,
>
> I'm having an FP issue that's sort of driving me crazy. I'm doing some division by 10, subtracting, and taking a floor. Purely mathematically, this is exactly what I want to do:
> ------
> num = 12;
> a = num/10;
> b = floor(a);
> c = a-b;
> d = 10*c;
> finalResult = floor(d);
> ------
>
> However, these are the results I get:
>
> ------
> a = num/10 = 1.2000000000000000
> b = floor(a) = 1.0000000000000000
> c = a - b = 0.2000000000000000
> d = 10*c = 1.9999999999999996
> Final Result = floor(d) = 1.0000000000000000
> ------
>
> But obviously, what I'm expecting mathematically is for the final result to be 2, not 1!
>
> I know FP gets tricky this way... But is there anyway around this?
>
> Basically, I'm doing this because I want to create a function that turns a number such as 3813919 into the array [3 8 1 3 9 1 9], and this was part of solving that problem (ie, decomposing a number into its digits). So if you have a good Matlab solution for that problem, that would also be a help.
>
> I figured out an algorithm that would do this decomposition, but the FP precision screws everything up!
>
> Thanks!
>
>
> fprintf('a = num/10 = %.16f\n', a);
> fprintf('b = floor(a) = %.16f\n', b);
> fprintf('c = a - b = %.16f\n', c);
> fprintf('d = 10*c = %.16f\n', d);
> fprintf('Final Result = floor(d) = %.16f\n', finalResult);
- - - - - - - - - -
Change your procedure just a little:

num = 749;

% Repeat this until num is zero
b = floor(num/10);
d = num-10*b; % The least tens' digit
num = b;

This way you will not suffer round off error.

Roger Stafford
From: Jan Simon on
Dear bogfrog,

> > Basically, I'm doing this because I want to create a function
> > that turns a number such as 3813919 into the array [3 8 1 3 9 1 9], ...
>
> dpd:
> >> digits=strread(sprintf('%d',3813919),'%1d')'
> digits =
> 3 8 1 3 9 1 9

Or simpler:
digits = sprintf('%d', 3813919) - '0';
This does an implicte conversion to DOUBLE, but I'd prefer to perform this manually to be compatible with future Matlab versions:
digits = double(sprintf('%d', 3813919) - '0');

Jan