[Algorithms] Tìm số nhỏ nhất trong 3 số không dùng phép so sánh
Bài đăng này đã không được cập nhật trong 8 năm
Đề bài: Viết chương trình (C) để tìm số nhỏ nhất trong 3 số.
1. Đơn giản nhất, dùng phép so sánh.
#include <stdio.h>
int smallest(int x, int y, int z)
{
if (x>y){
return y>z?z:y;
}
else{
return x>z?z:x;
}
}
int main()
{
int x = 12, y = 15, z = 5;
printf("%d", smallest(x, y, z));
return 0;
}
2. Nhưng không được dùng phép so sánh thì sao?
2.1. Sử dụng phương pháp trừ dần
Ta sử dụng 1 biến counter c
, khởi tạo c = 0
, chúng ta sẽ trừ dần giá trị đồng thời của x, y, z
cho 1
, với mỗi lần như vậy ta tăng c
lên 1
.
Số nhỏ nhất trong 3 số x, y, z
sẽ bằng 0
đầu tiên khi trừ dần như vậy. Và giá trị của c
sẽ là giá trị của số đó.
#include <stdio.h>
int smallest(int x, int y, int z)
{
int c = 0;
while ( x && y && z )
{
x--; y--; z--; c++;
}
return c;
}
int main()
{
int x = 12, y = 15, z = 5;
printf("%d", smallest(x, y, z));
return 0;
}
Nhưng cách này không sử dụng được với số âm.
2.2. Sử dụng phép chia
Ta để ý rằng trong C, 0 == false
, do vậy, nếu y < x
thì y/x == 0 == false
. Lợi dụng việc đó ta viết lại smallest
như sau:
#include <stdio.h>
int smallest(int x, int y, int z)
{
if(!(y/x)){
return !(z/y)?z:y;
}else{
return !(z/x)?z:x;
}
}
int main()
{
int x = 12, y = 15, z = 5;
printf("%d", smallest(x, y, z));
return 0;
}
Phương pháp này không sử dụng được khi 1 trong 3 giá trị của x, y, z
bằng 0
2.3. Sử dụng dịch bit và phép trừ
Ta nhận thấy rằng đối với 2 số x, y ta có INT_MIN <= (x-y) <= INT_MAX
Ta sẽ có giá trị min của x
và y
là:
min = y + ((x - y) & ((x - y) >>(sizeof(int) * CHAR_BIT - 1)))
Giải thích như sau: ta thấy rằng phép dịch giá trị (x-y)
sang phải 31
bits (CHAR_BIT*4 - 1
) sẽ cho ta biết (x-y) > 0
hay (x-y) < 0
.
Trong trường hợp (x-y) > 0
vậy bit thứ32
sẽ bằng 0
(bit 32
là bit dấu, 0
là dương, 1
là âm), ngược lại (x-y) < 0
thì bit 32
sẽ bằng 1
(bit dấu bằng 1
).
Vậy, trong trường hợp (x-y) > 0
hay x > y
:
min = y + (x-y)&0 // min == y
Ngược lại,
min = y + (x-y)&1 // min == x
Từ đó ta implement hàm tìm min
2 số như sau:
#define CHAR_BIT 8
int min(int x, int y){
return y + ((x - y) & ((x - y) >>(sizeof(int) * CHAR_BIT - 1)));
}
Từ đó ta có hàm tìm min
3 số như sau:
#include <stdio.h>
#define CHAR_BIT 8
int smallest(int x, int y, int z)
{
return min(x,min(y,z));
}
int min(int x, int y){
return y + ((x - y) & ((x - y) >>(sizeof(int) * CHAR_BIT - 1)));
}
int main()
{
int x = 12, y = 15, z = 5;
printf("%d", smallest(x, y, z));
return 0;
}
Trên đây là 3 cách để tìm min 3 số mà không dùng phép toán so sánh. Cảm ơn các bạn đã theo đọc hết bài. Hẹn gặp lại trong những thử thách thú vị khác.
ありがとうございます。
All rights reserved
Bình luận
Cách dễ hơn : viết 1 function get số lớn nhất giữa a và b, công thức : (a + b + (a-b).abs)/2 (abs là hàm giá trị tuyệt đối). áp dụng công thức này 2 lần ta tìm đc số lớn nhất trong 3 số.