From: Steven Lord on

"bogfrog" <aj00mcgraw(a)gmail.com> wrote in message
news: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:

*snip*

> 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?

Nope.

> 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.

Avoid doing calculations on non-flints at all.

x = 3813919;
onesDigit = mod(x, 10); % x is flint, 10 is flint, so onesDigit is flint
x = x-onesDigit; % flint-flint calculation; result is a flint multiple of 10
x = x/10; % no roundoff involved
% repeat

To preallocate your results array, you'd probably want to use
ceil(log10(x)), or simply assume you don't have more than 20 digits [for
intmax('uint64')] or (since your numbers are going to be small) grow the
array in the loop and FLIPLR it at the end. Yes, I know growing an array in
the loop is inefficient. But since the loop is very short, you're not going
to be reallocating memory that often.

On the plus side, the algorithm above also works with variables of integer
classes.

x = uint32(3813919);
nextDigit = 1;
digitVector = zeros(1, 21); % give some wiggle room
while x > 0
onesDigit = mod(x, 10);
x = (x-onesDigit)/10;
digitVector(nextDigit) = onesDigit;
nextDigit = nextDigit+1;
end
digitVector = digitVector(nextDigit-1:-1:1);

--
Steve Lord
slord(a)mathworks.com
comp.soft-sys.matlab (CSSM) FAQ: http://matlabwiki.mathworks.com/MATLAB_FAQ
To contact Technical Support use the Contact Us link on
http://www.mathworks.com


From: bogfrog on
>digits = double(sprintf('%d', 3813919) - '0');

This works beautifully, but what in the world is going on?

How does subtracting '0' turn this into an array of digits?
From: dpb on
bogfrog wrote:
>> digits = double(sprintf('%d', 3813919) - '0');
>
> This works beautifully, but what in the world is going on?
>
> How does subtracting '0' turn this into an array of digits?

The sprintf() has already turned it into an array of characters; the
subtraction does an implicit conversion back to numeric by ML design.
Look at the results in the command window of the pieces of the
expression individually to see what happens each step.

It's an historic ML idiom; I just kinda like the explicit recast via the
strread() as opposed to the above. AFAICT it's personal preference
although it's undoubtedly documentably faster by the numerical operation
by avoiding the internal i/o. But, unless one has a _very_ deep loop or
somesuch it's highly unlikely to be discernible.

--
From: us on
bogfrog <aj00mcgraw(a)gmail.com> wrote in message <1675532262.20705.1277390646666.JavaMail.root(a)gallium.mathforum.org>...
> >digits = double(sprintf('%d', 3813919) - '0');
>
> This works beautifully, but what in the world is going on?
>
> How does subtracting '0' turn this into an array of digits?

a hint:
- the DOUBLE typecast is not neccessary

d=sprintf('%d',1357)-'0' % <- or -48, ie, ASCII rep of CHAR '0'
% d = 1 3 5 7
% and the rather trivial trick behind it...
c=sprintf('%d',8)
% c = 8
% -or- its ASCII rep
a=sprintf('%d - %d',c,'0')
% a = 56 - 48
% thus,
56-48
% ans = 8

us
From: Jan Simon on
Dear us,

> a hint:
> - the DOUBLE typecast is not neccessary

Correct. I'm sheepish since Matlab changed the results:
Matlab 6.5: 'a':'c' => [97, 98, 99]
Matlab 7.?: 'a':'c' => 'abc'
Casting a DOUBLE to DOUBLE is really fast, so I prefer to cast the result of operations with CHARs explicitely.

Jan