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

266 ビュー (過去 30 日間)
Travis Cuvelier
Travis Cuvelier 2021 年 6 月 16 日
コメント済み: Steven Lord 2024 年 4 月 19 日 20:25
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.

採用された回答

Chunru
Chunru 2021 年 6 月 16 日
編集済み: Chunru 2021 年 6 月 16 日
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 件のコメント
Walter Roberson
Walter Roberson 2023 年 2 月 17 日
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 2023 年 2 月 17 日
編集済み: TylerTK 2023 年 2 月 17 日
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.

サインインしてコメントする。

その他の回答 (2 件)

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

uno
uno 2023 年 2 月 17 日
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 件のコメント
Thomas Bewley
Thomas Bewley 2024 年 4 月 19 日 15:01
編集済み: Thomas Bewley 2024 年 4 月 19 日 16:02
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 2024 年 4 月 19 日 20:25
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!

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeCharacters and Strings についてさらに検索

製品


リリース

R2021a

Community Treasure Hunt

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

Start Hunting!

Translated by