วิธีที่คุณจะแบ่งจำนวนโดยไม่ต้องใช้ 3 *
, /
, +
, -
, %
ผู้ประกอบการ?
หมายเลขอาจถูกเซ็นชื่อหรือไม่ได้ลงนาม
วิธีที่คุณจะแบ่งจำนวนโดยไม่ต้องใช้ 3 *
, /
, +
, -
, %
ผู้ประกอบการ?
หมายเลขอาจถูกเซ็นชื่อหรือไม่ได้ลงนาม
คำตอบ:
นี่คือฟังก์ชั่นที่เรียบง่ายซึ่งดำเนินการตามที่ต้องการ แต่มันต้องการ+
โอเปอเรเตอร์ดังนั้นสิ่งที่คุณต้องทำคือเพิ่มค่าด้วยตัวดำเนินการบิต:
// replaces the + operator
int add(int x, int y)
{
while (x) {
int t = (x & y) << 1;
y ^= x;
x = t;
}
return y;
}
int divideby3(int num)
{
int sum = 0;
while (num > 3) {
sum = add(num >> 2, sum);
num = add(num >> 2, num & 3);
}
if (num == 3)
sum = add(sum, 1);
return sum;
}
ตามที่จิมแสดงความคิดเห็นงานนี้เพราะ:
n = 4 * a + b
n / 3 = a + (a + b) / 3
ดังนั้นsum += a
, n = a + b
และสำทับ
เมื่อa == 0 (n < 4)
, sum += floor(n / 3);
คือ 1if n == 3, else 0
1 / 3 = 0.333333
a / 3 = a/10*3 + a/100*3 + a/1000*3 + (..)
ในไบนารีก็เกือบจะเหมือนกัน: ซึ่งนำไปสู่การ1 / 3 = 0.0101010101 (base 2)
a / 3 = a/4 + a/16 + a/64 + (..)
การหารด้วย 4 เป็นจุดที่การเปลี่ยนบิตมาจาก การตรวจสอบครั้งล่าสุดเกี่ยวกับ num == 3 เป็นสิ่งจำเป็นเพราะเรามีจำนวนเต็มเท่านั้นที่จะทำงานได้
a / 3 = a * 0.111111 (base 4) = a * 4^-1 + a * 4^-2 + a * 4^-3 + (..) = a >> 2 + a >> 4 + a >> 6 + (..)
. ฐาน 4 ยังอธิบายว่าทำไมเพียง 3 กลมในตอนท้ายขณะที่ 1 และ 2 สามารถปัดลงได้
n == 2^k
สิ่งต่อไปนี้เป็นจริง: x % n == x & (n-1)
ดังนั้นที่นี่num & 3
จะใช้เพื่อดำเนินการnum % 4
ในขณะที่%
ไม่ได้รับอนุญาต
เงื่อนไข Idiotic เรียกหาวิธีแก้ปัญหางี่เง่า:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE * fp=fopen("temp.dat","w+b");
int number=12346;
int divisor=3;
char * buf = calloc(number,1);
fwrite(buf,number,1,fp);
rewind(fp);
int result=fread(buf,divisor,number,fp);
printf("%d / %d = %d", number, divisor, result);
free(buf);
fclose(fp);
return 0;
}
ถ้าต้องการส่วนทศนิยมก็ประกาศด้วย result
เป็นและเพิ่มไปผลมาจากการdouble
fmod(number,divisor)
คำอธิบายวิธีการทำงาน
fwrite
เขียนnumber
ไบต์ (หมายเลข 123456 เป็นในตัวอย่างข้างต้น)rewind
รีเซ็ตตัวชี้ไฟล์ไว้ที่ด้านหน้าของไฟล์fread
อ่านnumber
"บันทึก" สูงสุดที่มีdivisor
ความยาวจากไฟล์และส่งกลับจำนวนองค์ประกอบที่อ่านหากคุณเขียน 30 ไบต์จากนั้นอ่านไฟล์ในหน่วย 3 คุณจะได้รับ 10 "หน่วย" 30/3 = 10
log(pow(exp(number),0.33333333333333333333)) /* :-) */
Math.log(Math.pow(Math.exp(709),0.33333333333333333333))
และMath.log(Math.pow(Math.exp(709),Math.sin(Math.atan2(1,Math.sqrt(8)))))
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int num = 1234567;
int den = 3;
div_t r = div(num,den); // div() is a standard C function.
printf("%d\n", r.quot);
return 0;
}
คุณสามารถใช้การประกอบแบบอินไลน์ (ขึ้นอยู่กับแพลตฟอร์ม) เช่นสำหรับ x86: (ใช้ได้กับจำนวนลบ)
#include <stdio.h>
int main() {
int dividend = -42, divisor = 5, quotient, remainder;
__asm__ ( "cdq; idivl %%ebx;"
: "=a" (quotient), "=d" (remainder)
: "a" (dividend), "b" (divisor)
: );
printf("%i / %i = %i, remainder: %i\n", dividend, divisor, quotient, remainder);
return 0;
}
asm
คำสั่งคือ และฉันจะเพิ่มว่าคอมไพเลอร์ C ไม่ใช่คนเดียวที่มีแอสเซมเบลอร์แบบอินไลน์ Delphi ก็มีเช่นกัน
asm
คำสั่งถูกกล่าวถึงเฉพาะในมาตรฐาน C99 ภายใต้ภาคผนวก J - ส่วนขยายทั่วไป
ใช้itoaเพื่อแปลงเป็นสตริง 3 ฐาน ปล่อยtritสุดท้ายแล้วแปลงกลับเป็นฐาน 10
// Note: itoa is non-standard but actual implementations
// don't seem to handle negative when base != 10.
int div3(int i) {
char str[42];
sprintf(str, "%d", INT_MIN); // Put minus sign at str[0]
if (i>0) // Remove sign if positive
str[0] = ' ';
itoa(abs(i), &str[1], 3); // Put ternary absolute value starting at str[1]
str[strlen(&str[1])] = '\0'; // Drop last digit
return strtol(str, NULL, 3); // Read back result
}
itoa
สามารถใช้ฐานโดยพลการ หากคุณใช้งานโดยใช้itoa
ฉันจะ upvote
/
และ%
... :-)
printf
เพื่อแสดงผลลัพธ์ทศนิยมของคุณ
(หมายเหตุ: ดูแก้ไข 2 ด้านล่างสำหรับรุ่นที่ดีกว่า!)
นี้ไม่ได้เป็นเรื่องยุ่งยากอย่างที่มันฟังเพราะคุณบอกว่า "โดยไม่ต้องใช้ [ .. ] +
[ .. ] ผู้ประกอบการ " ดูด้านล่างหากคุณต้องการห้ามใช้+
ตัวละครทั้งหมดเข้าด้วยกัน
unsigned div_by(unsigned const x, unsigned const by) {
unsigned floor = 0;
for (unsigned cmp = 0, r = 0; cmp <= x;) {
for (unsigned i = 0; i < by; i++)
cmp++; // that's not the + operator!
floor = r;
r++; // neither is this.
}
return floor;
}
แล้วก็บอกว่าdiv_by(100,3)
จะแบ่งโดย100
3
++
โอเปอเรเตอร์ได้เช่นกัน:unsigned inc(unsigned x) {
for (unsigned mask = 1; mask; mask <<= 1) {
if (mask & x)
x &= ~mask;
else
return x & mask;
}
return 0; // overflow (note that both x and mask are 0 here)
}
+
, -
, *
, /
, ตัวละคร%
unsigned add(char const zero[], unsigned const x, unsigned const y) {
// this exploits that &foo[bar] == foo+bar if foo is of type char*
return (int)(uintptr_t)(&((&zero[x])[y]));
}
unsigned div_by(unsigned const x, unsigned const by) {
unsigned floor = 0;
for (unsigned cmp = 0, r = 0; cmp <= x;) {
cmp = add(0,cmp,by);
floor = r;
r = add(0,r,1);
}
return floor;
}
เราใช้อาร์กิวเมนต์ตัวแรกของadd
ฟังก์ชั่นเพราะเราไม่สามารถแสดงชนิดของพอยน์เตอร์ได้โดยไม่ต้องใช้*
ตัวอักษรยกเว้นในรายการพารามิเตอร์ของฟังก์ชันโดยที่ไวยากรณ์type[]
นั้นเหมือนกับtype* const
เป็นเหมือน
FWIW คุณสามารถใช้ฟังก์ชันการคูณได้อย่างง่ายดายโดยใช้กลอุบายที่คล้ายกันเพื่อใช้0x55555556
เคล็ดลับที่เสนอโดยAndreyT :
int mul(int const x, int const y) {
return sizeof(struct {
char const ignore[y];
}[x]);
}
++
: ทำไมคุณไม่ใช้เพียง/=
?
++
ยังเป็นทางลัด: num = num + 1
สำหรับ
+=
num = num + 1
เป็นไปได้อย่างง่ายดายบนคอมพิวเตอร์ Setunคอมพิวเตอร์
หากต้องการหารจำนวนเต็ม 3 ให้เลื่อนไปทางขวา 1 ตำแหน่งสถานที่
ฉันไม่แน่ใจว่ามันเป็นไปได้อย่างเคร่งครัดที่จะใช้คอมไพเลอร์ที่สอดคล้องกับ C บนแพลตฟอร์มดังกล่าวหรือไม่ เราอาจต้องยืดกฎออกไปเล็กน้อยเช่นการตีความ "อย่างน้อย 8 บิต" เป็น "สามารถถือจำนวนเต็มอย่างน้อยจาก -128 ถึง +127"
>>
โอเปอเรเตอร์คือตัวดำเนินการ "หารด้วย 2 ^ n" นั่นคือมีการระบุในรูปของเลขคณิตไม่ใช่การแสดงด้วยเครื่อง
เนื่องจากมาจาก Oracle วิธีการเกี่ยวกับตารางการค้นหาคำตอบที่คำนวณไว้ล่วงหน้า :-D
นี่คือทางออกของฉัน:
public static int div_by_3(long a) {
a <<= 30;
for(int i = 2; i <= 32 ; i <<= 1) {
a = add(a, a >> i);
}
return (int) (a >> 32);
}
public static long add(long a, long b) {
long carry = (a & b) << 1;
long sum = (a ^ b);
return carry == 0 ? sum : add(carry, sum);
}
ก่อนอื่นให้สังเกตว่า
1/3 = 1/4 + 1/16 + 1/64 + ...
ตอนนี้ที่เหลือก็ง่าย!
a/3 = a * 1/3
a/3 = a * (1/4 + 1/16 + 1/64 + ...)
a/3 = a/4 + a/16 + 1/64 + ...
a/3 = a >> 2 + a >> 4 + a >> 6 + ...
ทีนี้สิ่งที่เราต้องทำก็คือการบวกค่าที่เปลี่ยนไปเล็กน้อยของ a! อ๊ะ! เราไม่สามารถเพิ่มได้ดังนั้นเราจะต้องเขียนฟังก์ชันเพิ่มโดยใช้ตัวดำเนินการ bit-wise! หากคุณคุ้นเคยกับตัวดำเนินการที่ชาญฉลาดโซลูชันของฉันควรดูค่อนข้างง่าย ... แต่ในกรณีที่คุณไม่ใช่ฉันจะอธิบายตัวอย่างในตอนท้าย
อีกสิ่งที่ควรทราบคือตอนแรกฉันเลื่อนไปทางซ้าย 30! นี่คือเพื่อให้แน่ใจว่าเศษส่วนจะไม่ถูกปัดเศษ
11 + 6
1011 + 0110
sum = 1011 ^ 0110 = 1101
carry = (1011 & 0110) << 1 = 0010 << 1 = 0100
Now you recurse!
1101 + 0100
sum = 1101 ^ 0100 = 1001
carry = (1101 & 0100) << 1 = 0100 << 1 = 1000
Again!
1001 + 1000
sum = 1001 ^ 1000 = 0001
carry = (1001 & 1000) << 1 = 1000 << 1 = 10000
One last time!
0001 + 10000
sum = 0001 ^ 10000 = 10001 = 17
carry = (0001 & 10000) << 1 = 0
Done!
มันเป็นแค่การเพิ่มเติมที่คุณได้เรียนรู้ตั้งแต่เด็ก!
111
1011
+0110
-----
10001
การนำไปใช้งานล้มเหลวเนื่องจากเราไม่สามารถเพิ่มเงื่อนไขทั้งหมดของสมการได้:
a / 3 = a/4 + a/4^2 + a/4^3 + ... + a/4^i + ... = f(a, i) + a * 1/3 * 1/4^i
f(a, i) = a/4 + a/4^2 + ... + a/4^i
สมมติว่า reslut ของdiv_by_3(a)
= x x <= floor(f(a, i)) < a / 3
แล้ว เมื่อไหร่a = 3k
เราจะได้คำตอบที่ผิด
n/3
อยู่เสมอน้อยกว่าn/3
ซึ่งหมายความว่าสำหรับการใด ๆn=3k
ผลจะเป็นแทนk-1
k
การหารตัวเลข 32- บิตด้วย 3 จะคูณด้วย 0x55555556
แล้วนำ 32 บิตด้านบนของผลลัพธ์ 64 บิต
ตอนนี้สิ่งที่ต้องทำคือการใช้การคูณโดยใช้การดำเนินการบิตและกะ ...
multiply it
. จะไม่ได้หมายความว่าใช้ตัว*
ดำเนินการต้องห้ามหรือไม่
อีกวิธีหนึ่ง สิ่งนี้ควรจัดการ int ทั้งหมด (รวมถึง ints เชิงลบ) ยกเว้นค่า min ของ int ซึ่งจะต้องได้รับการจัดการเป็นข้อยกเว้นที่กำหนดรหัสยาก สิ่งนี้จะทำการหารด้วยการลบ แต่ใช้ตัวดำเนินการบิตเท่านั้น (กะ, xor, และและส่วนเติมเต็ม) สำหรับความเร็วที่เพิ่มขึ้นจะลบ 3 * (ลดพลังของ 2) ใน c # จะมีการเรียก DivideBy3 ประมาณ 444 ครั้งต่อมิลลิวินาที (2.2 วินาทีสำหรับ 1,000,000 ครั้ง) ดังนั้นจึงไม่ช้าอย่างน่ากลัว แต่ไม่มีที่ไหนใกล้เร็วเท่า x / 3 อย่างง่าย โดยเปรียบเทียบโซลูชั่นที่ดีของ Coodey เร็วกว่านี้ประมาณ 5 เท่า
public static int DivideBy3(int a) {
bool negative = a < 0;
if (negative) a = Negate(a);
int result;
int sub = 3 << 29;
int threes = 1 << 29;
result = 0;
while (threes > 0) {
if (a >= sub) {
a = Add(a, Negate(sub));
result = Add(result, threes);
}
sub >>= 1;
threes >>= 1;
}
if (negative) result = Negate(result);
return result;
}
public static int Negate(int a) {
return Add(~a, 1);
}
public static int Add(int a, int b) {
int x = 0;
x = a ^ b;
while ((a & b) != 0) {
b = (a & b) << 1;
a = x;
x = a ^ b;
}
return x;
}
นี่คือ c # เพราะนั่นคือสิ่งที่ฉันมีประโยชน์ แต่ความแตกต่างจาก c ควรเป็นรอง
(a >= sub)
นับเป็นลบหรือไม่?
มันค่อนข้างง่ายจริงๆ
if (number == 0) return 0;
if (number == 1) return 0;
if (number == 2) return 0;
if (number == 3) return 1;
if (number == 4) return 1;
if (number == 5) return 1;
if (number == 6) return 2;
(แน่นอนว่าฉันได้ละเว้นโปรแกรมบางอย่างเพื่อความกะทัดรัด) หากโปรแกรมเมอร์เบื่อที่จะพิมพ์สิ่งนี้ออกมาทั้งหมดฉันแน่ใจว่าเขาหรือเธอสามารถเขียนโปรแกรมแยกต่างหากเพื่อสร้างมันขึ้นมาให้เขา ฉันบังเอิญได้ตระหนักถึงโอเปอเรเตอร์บางอย่าง/
ที่จะทำให้งานของเขาง่ายขึ้นอย่างมาก
Dictionary<number, number>
แทนif
คำซ้ำเพื่อให้คุณมีO(1)
เวลาที่ซับซ้อน!
การใช้ตัวนับเป็นโซลูชันพื้นฐาน:
int DivBy3(int num) {
int result = 0;
int counter = 0;
while (1) {
if (num == counter) //Modulus 0
return result;
counter = abs(~counter); //++counter
if (num == counter) //Modulus 1
return result;
counter = abs(~counter); //++counter
if (num == counter) //Modulus 2
return result;
counter = abs(~counter); //++counter
result = abs(~result); //++result
}
}
นอกจากนี้ยังง่ายต่อการใช้งานฟังก์ชั่นโมดูลัสตรวจสอบความคิดเห็น
อันนี้เป็นอัลกอริธึมการแบ่งแบบคลาสสิกในฐาน 2:
#include <stdio.h>
#include <stdint.h>
int main()
{
uint32_t mod3[6] = { 0,1,2,0,1,2 };
uint32_t x = 1234567; // number to divide, and remainder at the end
uint32_t y = 0; // result
int bit = 31; // current bit
printf("X=%u X/3=%u\n",x,x/3); // the '/3' is for testing
while (bit>0)
{
printf("BIT=%d X=%u Y=%u\n",bit,x,y);
// decrement bit
int h = 1; while (1) { bit ^= h; if ( bit&h ) h <<= 1; else break; }
uint32_t r = x>>bit; // current remainder in 0..5
x ^= r<<bit; // remove R bits from X
if (r >= 3) y |= 1<<bit; // new output bit
x |= mod3[r]<<bit; // new remainder inserted in X
}
printf("Y=%u\n",y);
}
เขียนโปรแกรมใน Pascal และใช้ DIV
โอเปอเรเตอร์
เนื่องจากคำถามถูกติดแท็ก คคุณอาจจะสามารถเขียนฟังก์ชั่นใน Pascal และเรียกมันจากโปรแกรม C ของคุณ วิธีการทำเช่นนั้นเป็นระบบเฉพาะ
แต่นี่เป็นตัวอย่างที่ทำงานบนระบบ Ubuntu ของฉันเมื่อfp-compiler
ติดตั้งแพ็คเกจPascal ฟรี (ฉันกำลังทำสิ่งนี้ออกมาจากความดื้อรั้นอย่างไร้ที่ติ; ฉันไม่อ้างว่าสิ่งนี้มีประโยชน์)
divide_by_3.pas
:
unit Divide_By_3;
interface
function div_by_3(n: integer): integer; cdecl; export;
implementation
function div_by_3(n: integer): integer; cdecl;
begin
div_by_3 := n div 3;
end;
end.
main.c
:
#include <stdio.h>
#include <stdlib.h>
extern int div_by_3(int n);
int main(void) {
int n;
fputs("Enter a number: ", stdout);
fflush(stdout);
scanf("%d", &n);
printf("%d / 3 = %d\n", n, div_by_3(n));
return 0;
}
สร้าง:
fpc divide_by_3.pas && gcc divide_by_3.o main.c -o main
ตัวอย่างการดำเนินการ:
$ ./main
Enter a number: 100
100 / 3 = 33
int div3(int x)
{
int reminder = abs(x);
int result = 0;
while(reminder >= 3)
{
result++;
reminder--;
reminder--;
reminder--;
}
return result;
}
ADD
และINC
พวกเขาไม่มี opcodes เดียวกัน
ไม่ได้ตรวจสอบข้ามว่าคำตอบนี้ได้รับการเผยแพร่แล้ว หากโปรแกรมจำเป็นต้องขยายไปยังตัวเลขลอยตัวตัวเลขนั้นสามารถคูณด้วยจำนวนความแม่นยำ 10 * ตามที่ต้องการและจากนั้นจะสามารถใช้รหัสต่อไปนี้อีกครั้ง
#include <stdio.h>
int main()
{
int aNumber = 500;
int gResult = 0;
int aLoop = 0;
int i = 0;
for(i = 0; i < aNumber; i++)
{
if(aLoop == 3)
{
gResult++;
aLoop = 0;
}
aLoop++;
}
printf("Reulst of %d / 3 = %d", aNumber, gResult);
return 0;
}
สิ่งนี้ควรใช้กับตัวหารใด ๆ ไม่ใช่แค่สามตัวเท่านั้น ขณะนี้มีเฉพาะสำหรับผู้ที่ไม่ได้ลงชื่อ แต่การขยายไปยังการลงชื่อไม่น่ายาก
#include <stdio.h>
unsigned sub(unsigned two, unsigned one);
unsigned bitdiv(unsigned top, unsigned bot);
unsigned sub(unsigned two, unsigned one)
{
unsigned bor;
bor = one;
do {
one = ~two & bor;
two ^= bor;
bor = one<<1;
} while (one);
return two;
}
unsigned bitdiv(unsigned top, unsigned bot)
{
unsigned result, shift;
if (!bot || top < bot) return 0;
for(shift=1;top >= (bot<<=1); shift++) {;}
bot >>= 1;
for (result=0; shift--; bot >>= 1 ) {
result <<=1;
if (top >= bot) {
top = sub(top,bot);
result |= 1;
}
}
return result;
}
int main(void)
{
unsigned arg,val;
for (arg=2; arg < 40; arg++) {
val = bitdiv(arg,3);
printf("Arg=%u Val=%u\n", arg, val);
}
return 0;
}
มันจะเป็นการโกงที่จะใช้/
โอเปอเรเตอร์ "เบื้องหลัง" โดยใช้eval
และการต่อสตริงหรือไม่?
ตัวอย่างเช่นใน Javacript คุณสามารถทำได้
function div3 (n) {
var div = String.fromCharCode(47);
return eval([n, div, 3].join(""));
}
<?php
$a = 12345;
$b = bcdiv($a, 3);
?>
MySQL (เป็นการสัมภาษณ์จาก Oracle)
> SELECT 12345 DIV 3;
ปาสกาล :
a:= 12345;
b:= a div 3;
ภาษาแอสเซมบลี x86-64:
mov r8, 3
xor rdx, rdx
mov rax, 12345
idiv r8
อย่างแรกที่ฉันคิดไว้
irb(main):101:0> div3 = -> n { s = '%0' + n.to_s + 's'; (s % '').gsub(' ', ' ').size }
=> #<Proc:0x0000000205ae90@(irb):101 (lambda)>
irb(main):102:0> div3[12]
=> 4
irb(main):103:0> div3[666]
=> 222
แก้ไข:C
ขอโทษนะฉันไม่ได้สังเกตเห็นแท็ก แต่คุณสามารถใช้ความคิดเกี่ยวกับการจัดรูปแบบสตริงฉันเดา ...
สคริปต์ต่อไปนี้สร้างโปรแกรม C ที่แก้ปัญหาโดยไม่ใช้ตัวดำเนินการ* / + - %
:
#!/usr/bin/env python3
print('''#include <stdint.h>
#include <stdio.h>
const int32_t div_by_3(const int32_t input)
{
''')
for i in range(-2**31, 2**31):
print(' if(input == %d) return %d;' % (i, i / 3))
print(r'''
return 42; // impossible
}
int main()
{
const int32_t number = 8;
printf("%d / 3 = %d\n", number, div_by_3(number));
}
''')
การใช้เครื่องคิดเลขตัวเลข Delight Magic ของแฮ็กเกอร์
int divideByThree(int num)
{
return (fma(num, 1431655766, 0) >> 32);
}
โดยที่fmaเป็นฟังก์ชันไลบรารีมาตรฐานที่กำหนดไว้ในmath.h
ส่วนหัว
-
ตัว*
ดำเนินการหรือตัวดำเนินการ
วิธีการเกี่ยวกับวิธีนี้ (c #)
private int dividedBy3(int n) {
List<Object> a = new Object[n].ToList();
List<Object> b = new List<object>();
while (a.Count > 2) {
a.RemoveRange(0, 3);
b.Add(new Object());
}
return b.Count;
}
ฉันคิดว่าคำตอบที่ถูกคือ:
ทำไมฉันจะไม่ใช้ตัวดำเนินการพื้นฐานเพื่อทำการดำเนินการพื้นฐาน
โซลูชันที่ใช้ฟังก์ชันไลบรารี fma ()ทำงานได้กับจำนวนบวกใด ๆ :
#include <stdio.h>
#include <math.h>
int main()
{
int number = 8;//Any +ve no.
int temp = 3, result = 0;
while(temp <= number){
temp = fma(temp, 1, 3); //fma(a, b, c) is a library function and returns (a*b) + c.
result = fma(result, 1, 1);
}
printf("\n\n%d divided by 3 = %d\n", number, result);
}
ใช้cblasซึ่งรวมเป็นส่วนหนึ่งของเฟรมเวิร์ก Accelerate ของ OS X
[02:31:59] [william@relativity ~]$ cat div3.c
#import <stdio.h>
#import <Accelerate/Accelerate.h>
int main() {
float multiplicand = 123456.0;
float multiplier = 0.333333;
printf("%f * %f == ", multiplicand, multiplier);
cblas_sscal(1, multiplier, &multiplicand, 1);
printf("%f\n", multiplicand);
}
[02:32:07] [william@relativity ~]$ clang div3.c -framework Accelerate -o div3 && ./div3
123456.000000 * 0.333333 == 41151.957031
โดยทั่วไปวิธีแก้ปัญหานี้จะเป็น:
log(pow(exp(numerator),pow(denominator,-1)))
ครั้งแรก:
x/3 = (x/4) / (1-1/4)
จากนั้นหาวิธีแก้ x / (1 - y):
x/(1-1/y)
= x * (1+y) / (1-y^2)
= x * (1+y) * (1+y^2) / (1-y^4)
= ...
= x * (1+y) * (1+y^2) * (1+y^4) * ... * (1+y^(2^i)) / (1-y^(2^(i+i))
= x * (1+y) * (1+y^2) * (1+y^4) * ... * (1+y^(2^i))
ด้วย y = 1/4:
int div3(int x) {
x <<= 6; // need more precise
x += x>>2; // x = x * (1+(1/2)^2)
x += x>>4; // x = x * (1+(1/2)^4)
x += x>>8; // x = x * (1+(1/2)^8)
x += x>>16; // x = x * (1+(1/2)^16)
return (x+1)>>8; // as (1-(1/2)^32) very near 1,
// we plus 1 instead of div (1-(1/2)^32)
}
แม้ว่ามันจะใช้+
แต่ใครบางคนได้ดำเนินการเพิ่มโดย bitwise op