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

169 visualizaciones (últimos 30 días)
Travis Cuvelier
Travis Cuvelier el 16 de Jun. de 2021
Comentada: Steven Lord el 19 de Abr. de 2024
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.

Respuesta aceptada

Chunru
Chunru el 16 de Jun. de 2021
Editada: Chunru el 16 de Jun. de 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 comentarios
Walter Roberson
Walter Roberson el 17 de Feb. de 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 el 17 de Feb. de 2023
Editada: TylerTK el 17 de Feb. de 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.

Iniciar sesión para comentar.

Más respuestas (2)

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

uno
uno el 17 de Feb. de 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 comentarios
Thomas Bewley
Thomas Bewley el 19 de Abr. de 2024
Editada: Thomas Bewley el 19 de Abr. de 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 el 19 de Abr. de 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!

Iniciar sesión para comentar.

Categorías

Más información sobre Logical en Help Center y File Exchange.

Etiquetas

Productos


Versión

R2021a

Community Treasure Hunt

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

Start Hunting!

Translated by