How does division "/" = work for integer types?

174 views (last 30 days)
In doing some work with integers in R2021A I noticed something relatively strange, namely that if A and B are unsigned integers and A >= B/2, then A/B = 1. Before today, I was not aware of this "rounding". In fact this doesn't quite jive with the documentation. In particular, uint32(1)/uint32(2) gives 1, wheras bitshift(uint32(1),-1) gives 0. Per the documentation https://www.mathworks.com/help/matlab/ref/bitshift.html, a bitshift of -1 should give the same result as dividing by 2. Is this expected behavior? I've attached a screenshot.

Accepted Answer

Chunru
Chunru on 16 Jun 2021
Edited: Chunru on 16 Jun 2021
MATLAB rounds the results when dividing integer data types. That is to say:
uint32(1) /uint32(2) = round(1/2) = round(0.5) =1
uint32(1)/uint32(2)
ans = uint32 1
uint32(10)/uint32(3)
ans = uint32 3
uint32(5)/uint32(2)
ans = uint32 3
  3 Comments
Walter Roberson
Walter Roberson on 17 Feb 2023
Integer division has no "natural" behaviour for remainders (except perhaps to offer to return the remainder separately).
What does "truncate" mean, exactly? Is it "round towards 0", or is it "floor" ? And should the result be different for 5/-2 than for -5/2 ?
TylerTK
TylerTK on 17 Feb 2023
Edited: TylerTK on 17 Feb 2023
I disagree. The natural behavior on processor system and in math courses would be drop fractional values (round toward 0). 1 doesn't consist of 1 group of 2.

Sign in to comment.

More Answers (2)

Steven Lord
Steven Lord on 16 Jun 2021
See the "Creating Integer Data" and "Arithmetic Operations on Integer Classes" sections on this documentation page.

uno
uno on 17 Feb 2023
Stumbled on this since I've just encontered the same issue. Totally nuts and I believe should be fixed.
Seems at the moment the solution is to use the idivide() function.
  15 Comments
Thomas Bewley
Thomas Bewley on 19 Apr 2024
Edited: Thomas Bewley on 19 Apr 2024
Paul - Yes, Fortran is consistent with C and Ada and all C-like programs that I am aware of (Rust, etc) in this regard. Yet, still inexplicably, in modern Matlab:
>> a=int8(-8); b=int8(3); a/b
ans =
int8
-3
Matlab is apparently the only programming language in the world today which does not do integer division in the standard way: "Integer division and remainder are defined by the relation A = (A/B)*B + (A rem B), where (A rem B) has the sign of A and an absolute value less than the absolute value of B. Integer division satisfies the identity (-A)/B = -(A/B) = A/(-B)."
AFAIK, rereading the above thread, Walter Roberson still hasn't motivated why Matlab implements its nonstandard choice (rounding to the nearest integer), which (I believe it can be reasonably argued) is error-prone due to its failure to satisfy the above stated standard definition, other than to state his preference for yet a third definition (rounding towards negative infinity, which fails to satisfy the above stated identity) as his humble opinion. I request that a committee of persons who are experienced in modern integer programming applications at Mathworks review the arguments laid out in this thread, and come up with a more deliberate path forward.
Steven Lord
Steven Lord on 19 Apr 2024
Let's look at one of the examples you posted:
a=uint8(7);
b=uint8(4);
answer1=a/b
answer1 = uint8 2
answer2=idivide(a,b)
answer2 = uint8 1
Would it be useful if a/b were to give the same answer as uint8(double(a)/double(b)), since both a and b are exactly representable in double precision? In other words, should it matter if you convert between double and uint8 before or after performing the division? [This same holds for the six smaller integer types; 64-bit integers have the complication that not all int64 or uint64 values are exactly representable in double precision.]
answer3 = uint8(double(a)/double(b))
answer3 = uint8 2
answer3b = uint8(7/4)
answer3b = uint8 2
If we look at a slightly different example:
answer4a = uint8(5/4)
answer4a = uint8 1
answer4b = uint8(5)/uint8(4)
answer4b = uint8 1
From the documentation: "If the number being converted to an integer has a fractional part, MATLAB rounds to the nearest integer."
By the way, if you're looking for integer arithmetic in MATLAB (using the operators) to exactly match C's behavior, it doesn't. Integer arithmetic in MATLAB saturates for both signed and unsigned integers instead of wrapping for unsigned integers like C. [And doing a little archaeology as well as remembering some of the discussions, "saturate or wrap" was quite vigorously debated internally when we first introduced integer arithmetic back in 2004 in release R14.]
x = intmax('uint8')
x = uint8 255
y = x+1 % saturates so y is the same as x, not wrapped to 0
y = uint8 255
If you're doing image processing on integer image data x, x+1 always being greater than or equal to x is probably a Good Thing.
But if you disagree with the choice of behavior for the backslash operator, you have a solution that you've already identified: use idivide. If I recall correctly, providing C style division was the main motivating factor for its existence!

Sign in to comment.

Products


Release

R2021a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!