* और + ऑपरेटरों का उपयोग किए बिना गुणन के लिए एक सी प्रोग्राम कैसे लिखें?


68

क्या एक सी प्रोग्राम लिखना संभव है जो गुणा और जोड़ ऑपरेटरों का उपयोग किए बिना दो संख्याओं को गुणा करता है?

मैंने इसे स्टैक ओवरफ्लो पर पाया । कृपया इस गरीब प्रोग्रामर को उसकी समस्या में मदद करें। और कृपया उत्तर न दें c = a/(1/((float)b)), जो बिल्कुल वैसा ही है जैसा कि है c = a*b। (और पहले से ही एक जवाब के रूप में दिया गया है।)

19 जनवरी 2014 को सबसे अधिक उत्थान के साथ उत्तर जीता।

नोट: यह एक प्रश्न है। कृपया प्रश्न और / या उत्तर को गंभीरता से न लें। अधिक जानकारी कोड-ट्रोलिंग में है


2
@PaRR अपनी कल्पना का उपयोग करें
जॉन ड्वोरक

26
Code-golf.SE आपके लिए उन सवालों का मजाक उड़ाने की जगह नहीं होनी चाहिए जो आपने StackOverflow पर देखे हैं।
गारेथ

17
@ गैरेथ, क्या आपको यकीन है? इसकी पहली पंक्ति यह बताती है कि यह काफी उपयुक्त हो सकता है।
डैरेन स्टोन

5
मैं किसी के इंतजार में नींद के आधार पर एक एल्गोरिथ्म
लिखता हूं

21
यह सवाल उतना हास्यास्पद नहीं है जितना लगता है। वास्तविक कंप्यूटर हार्डवेयर (ट्रांजिस्टर) में गुणा नहीं है और ऑपरेशन नहीं जोड़ते हैं - उनके पास बुनियादी तर्क संचालन जैसे कि NOT, AND, OR, XOR है। यह पता लगाने के लिए कि इस प्रश्न का उत्तर कैसे दिया जाए, इससे आपको उत्कृष्ट जानकारी मिल सकती है कि कंप्यूटर वास्तव में तर्क द्वार के स्तर पर कैसे काम करता है।
गाबे

जवाबों:


147

हमेशा पुनरावृत्ति का उपयोग करें

पुनरावृत्ति सही तरीका है!

int inc(int x) {
    return x&1?inc(x>>1)<<1:x|1;
}

int dec(int x) {
    return x&1?x^1:dec(x>>1)<<1|1;
}

int add(int x, int y) {
    return x?add(dec(x),inc(y)):y;
}

int mul(int x, int y) {
    return x?x^1?add(y,mul(dec(x),y)):y:0;
}

int main() {
    int a, b;
    scanf("%i\n%i", &a, &b);
    printf("%i", mul(a,b));
}

8
मैं +3 देता अगर मैं कर सकता था: एक अंतिम पुनरावृत्ति के लिए, एक ??::बिना कोष्ठक के लिए, एक नियम को टालने की कोशिश किए बिना समस्या को हल करने के लिए;)
यो

10
अगर पिकासो एक प्रोग्रामर थे ...
R Hughes

4
@SargeBorsch लेकिन मज़ा कहाँ में हो कि ?
ओबेरॉन

3
@HC_ incफ़ंक्शन सबसे कम बिट है यह देखने के लिए अपने तर्क का परीक्षण करता है 1; यदि ऐसा है, तो यह तर्क के शेष ऊपरी बिट्स पर खुद को कॉल करता है और परिणाम को उसी कम बिट के साथ लौटाता है जिसे चेक किए जाने पर सेट किया गया था 0, जबकि यदि नहीं (यानी सबसे कम बिट है 0), तो यह बदलता है कि परिणाम के 0साथ 1और परिणाम देता है । यदि आप हाथ से मान जोड़ रहे हैं, तो बाइनरी अंक से बाइनरी अंक, प्रक्रिया बहुत समान है।
जेएबी

2
क्या इंक्रीमेंट फ़ंक्शन -1 के लिए अनंत लूप में नहीं जाता है? (0xFFFF) आइडोन शो (-1 >> 1) == -1।
डेस्टिनेटर

87

आपको हर बार कार्यक्रम को संकलित करना होगा, लेकिन यह सी या सी ++ के किसी भी संस्करण में किसी भी सकारात्मक पूर्णांक का गुणन करता है।

 #define A 45  // first number
 #define B 315 // second number

 typedef char buffer[A][B];

 main() {
    printf("%d\n",sizeof(buffer));
 }

4
इसे एक संरचना के अंदर रखें और आपको मेमोरी की आवश्यकता नहीं है।
बेन जैक्सन

4
हाहाहाह महान !!
अल्मो

1
"%zu"प्रारूप स्ट्रिंग का उपयोग करें ।
बृजेश चौहान

5
बस sizeof(char[A][B])काम करेगा (जब तक कि ए <= 0 या बी <= 0 या ए * बी ओवरफ्लो न हो, जिस स्थिति में आपको 'खराब प्रकार' की त्रुटि मिलनी चाहिए)
greggo

3
@DavidRicherby - मैं कोड को सरल कर सकता हूं main(){return sizeof(char[A][B]);}और आप का उपयोग कर संकलन कर सकते हैंcc -DA=6 -DB=7 a.c; ./a.out; echo $?
मार्क Lakata

47

यदि आप थोड़े से दोष के साथ ठीक हैं, तो आप मोंटे कार्लो विधि का उपयोग कर सकते हैं :

#include <stdlib.h>
#include <stdio.h>

unsigned int mul(unsigned short a, unsigned short b) {
  const int totalBits = 24;
  const int total = (1 << totalBits);
  const int maxNumBits = 10;
  const int mask = (1 << maxNumBits) - 1;
  int count = 0, i;
  unsigned short x, y;
  for(i = 0; i < total; i++) {
    x = random() & mask;
    y = random() & mask;
    if ((x < a) && (y < b))
      count++;
  }
  return ((long)count) >> (totalBits - (maxNumBits << 1));
}

void main(int argc, char *argv[]) {
  unsigned short a = atoi(argv[1]);
  unsigned short b = atoi(argv[2]);
  printf("%hd * %hd = %d\n", a, b, mul(a, b));
}

उदाहरण:

$ ./mul 300 250
300 * 250 = 74954

मुझे लगता है कि यह काफी अच्छा हो सकता है;)


3
आपका वोट मेरे पास है। मैंने सुना है मोंटे कार्लो वह है जो नासा अपने अंकगणित के लिए उपयोग करता है। लेकिन मैं इसे ++ऑपरेटर के दो उदाहरणों के बिना देखना चाहता हूं ।
डैरेन स्टोन

1
@ डारेनस्टोन-= -1
20

20
@ टिमटेक |= 1(50% नंबरों पर काम करेगा, 100% समय)
डैरेन स्टोन

2
+1, लेकिन यह देखते हुए कि यह बहुत धीमा हो सकता है, और आप बहु-थ्रेड समर्थन जोड़ सकते हैं, ध्यान से 'गिनती ++' :-) को लॉक कर सकते हैं
greggo

1
हमेशा printfवेतन वृद्धि होती है: printf("%*cc%n\n", count, &count, 'c');(प्रिंट्स का 'सी' काउंट बार, फिर एक और 'सी', और वापस लिखे गए अक्षरों की संख्या को स्टोर करता है count
MSalters

45

चूंकि आपने संख्या का आकार निर्दिष्ट नहीं किया है, इसलिए मैं मानता हूं कि आपका मतलब दो एक-बिट संख्या है।

#include <stdbool.h>
bool mul(bool a, bool b) {
    if (a && b) {
        return true;
    } else {
        return false;
    }
}

यदि आप एक अधिकतम-कुशल कार्यान्वयन चाहते हैं, तो निम्नलिखित छोटे कार्यान्वयन का उपयोग करें:

m(a,b){return a&b;}

ध्यान दें कि यह अभी भी केवल बिट्स को स्वीकार करता है, भले ही प्रकार अंतर्निहित संकेत हैं - यह कम कोड लेता है, और इसलिए अधिक कुशल है। (और हाँ, यह संकलन करता है।)


8
अच्छा लगा। प्रश्न का एक जानबूझकर गलत अर्थ :-)
जॉन ड्वोरक

6
आप इसे अनुकूलित कर सकते हैं return a && b;। यह छोटा है, इसलिए यह तेज है।
Ry-

1
@ मिनिटेक: मैंने कोड को थोड़ा खराब करने के लिए इसके खिलाफ फैसला किया। अगर मैं इसके साथ आगे जाना चाहता था, तो मैं इसे बनाऊंगा return a&b;
सेल स्केग्ज

1
सी है #include<stdbool.h>परिभाषित करने के लिए trueऔर false
लीव्ज

1
हाँ, #include<stdbool.h>सिर्फ तीन प्रतीत हो रहा है #define(रों कि आप अपने आप क्या कर सकते हैं true, false, bool, और एक झंडा चिह्नित करने के लिए है कि यह सक्रिय कर दिया गया है)। आप अन्य उत्तरों में से एक से एक ट्रिक भी ले सकते हैं और int"लघु" संस्करण के लिए निहित का उपयोग कर सकते हैं ।
leewz

31

यहाँ यह करने के लिए एक सरल शेल स्क्रिप्ट है:

curl "http://www.bing.com/search?q=$1%2A$2&go=&qs=n&form=QBLH&pq=$1%2A$2" -s \
| sed -e "s/[<>]/\n/g" \
| grep "^[0-9 *]*=[0-9 ]*$"

अद्यतन: बेशक, इसे सी में करने के लिए, बस इसे लपेटें exec("bash", "-c", ...)। (साभार, अमेलियाबीआर)


41
मैं तय नहीं कर सकता कि कौन अधिक भयानक है। आप अपनी गणना को किसी खोज इंजन पर आउटसोर्सिंग कर रहे हैं, या आपका चुना हुआ खोज इंजन Bing है। दुर्भाग्य से, मुझे नहीं लगता कि यह हमारे खुशहाल ओपी के लिए काम करेगा, जिन्हें सी में कुछ चाहिए था
अमेलियाबीआर

5
उस निरीक्षण को पकड़ने के लिए धन्यवाद। FYI करें, मैं बिंग का उपयोग कर रहा हूं क्योंकि Google इस तरह के अनुरोधों को जारी करने के लिए और अधिक जटिल बनाता है - आपको Google को समझाने के लिए हेडर जोड़ना होगा आपका अनुरोध वास्तव में एक ब्राउज़र से आ रहा है।
व्रू

2
@abarnert हम्म ... क्या बिंग "बार" को समझता है? वुल्फराम अल्फा हालांकि, हो सकता है।
जॉन ड्वोरक

2
@JanDvorak: हाँ, Wolfram काम करता है। ( %20किसी भी +संकेत का उपयोग करने से बचने के लिए ध्यान दें ।) लेकिन आपको इसके मूल्य को प्राप्त करने के लिए आउटपुट (सी) में पार्स करने की आवश्यकता है। जो विशेष रूप से मुश्किल होगा, क्योंकि आउटपुट एक छवि प्रतीत होता है, पाठ नहीं। HTML पार्सिंग प्लस ओसीआर इस समस्या का सबसे अच्छा संभव जवाब हो सकता है।
abarnert

3
@JDDvorak: यह कोई मज़ा नहीं है। मैं किसी और के साथ एक साधारण OCR पुस्तकालय लिखने के लिए आगे देख रहा था या गुणा…
12

27

क्यों, चलो INT64_MIN और INT64_MAX के बीच एक पुनरावर्ती पड़ाव खोज करते हैं!

#include <stdio.h>
#include <stdint.h>

int64_t mul_finder(int32_t a, int32_t b, int64_t low, int64_t high)
{
    int64_t result = (low - (0 - high)) / 2;
    if (result / a == b && result % a == 0)
        return result;
    else
        return result / a < b ?
            mul_finder(a, b, result, high) :
            mul_finder(a, b, low, result);
}

int64_t mul(int32_t a, int32_t b)
{
    return a == 0 ? 0 : mul_finder(a, b, INT64_MIN, INT64_MAX);
}

void main(int argc, char* argv[])
{
    int32_t a, b;
    sscanf(argv[1], "%d", &a);
    sscanf(argv[2], "%d", &b);
    printf("%d * %d = %ld\n", a, b, mul(a, b));
}

पुनश्च यह खुशी से कुछ मूल्यों के साथ sigsegv होगा। ;)


18

दुर्भाग्य से, यह केवल पूर्णांकों के लिए काम करता है।

चूँकि यह अस्वीकृत है, इसलिए पहले एक वेतन वृद्धि ऑपरेटर बनाएँ:

int plusOne(int arg){
  int onMask = 1;
  int offMask = -1;
  while (arg & onMask){
    onMask <<= 1;
    offMask <<= 1;
  }
  return(arg & offMask | onMask);
}

अगला, हमें संकेत को संभालना होगा। सबसे पहले, साइन बिट ढूंढें:

int signBit = -1;
while(signBit << 1) signBit <<=1;

फिर प्रत्येक तर्क का संकेत और परिमाण लें। एक दो के पूरक में एक संख्या को नकारने के लिए, सभी बिट्स को उल्टा करें, और एक को जोड़ें।

int signA = a & signBit;
if(signA) a = plusOne(-1 ^ a);
int signB = b & signBit;
if(signB) b = plusOne(-1 ^ b);
int signRes = signA ^ signB;

दो सकारात्मक पूर्णांकों को गुणा करने के लिए, हम गुणन के ज्यामितीय अर्थ का उपयोग कर सकते हैं:

// 3x4
//
// ooo
// ooo
// ooo
// ooo

int res = 0;
for(int i = 0; i < a; i = plusOne(i))
  for(int j = 1; j < b; j = plusOne(j))
    res = plusOne(res);

if(signRes) res = plusOne(-1 ^ res);

trolls:

  • जोड़-घटाव है, लेकिन क्या a++वास्तव में इसके अलावा गिनती है? मैंने शर्त लगाई कि शिक्षक इसे अनुमति दें।
  • दो के पूरक पर निर्भर करता है, लेकिन यह एक कार्यान्वयन-परिभाषित व्यवहार है और लक्ष्य मंच निर्दिष्ट नहीं किया गया था।
  • इसी तरह, मान लिया जाता है कि घटाव और विभाजन को भी रोक दिया जाता है।
  • << वास्तव में दो की शक्ति से गुणा है, इसलिए इसे तकनीकी रूप से अस्वीकृत किया जाना चाहिए।
  • अकारण आरेख अनावश्यक है। साथ ही, एक लाइन को बचाने के लिए इसे ट्रांसपोज़ किया जा सकता था।
  • दोहराया की स्थानांतरण -1संकेत बिट खोजने का सबसे अच्छा तरीका नहीं है। यहां तक ​​कि अगर कोई अंतर्निर्मित स्थिरांक नहीं था, तो आप सही -1 का तार्किक बदलाव कर सकते हैं, फिर सभी बिट्स को उल्टा कर सकते हैं।
  • XOR -1 सभी बिट्स को पलटने का सबसे अच्छा तरीका नहीं है।
  • साइन-परिमाण प्रतिनिधित्व के साथ संपूर्ण वर्णक्रम अप्रमाणिक है। बस अहस्ताक्षरित और मॉड्यूलर अंकगणित के लिए डाली बाकी करेंगे।
  • चूंकि MIN_INT(AKA signBit) का निरपेक्ष मान ऋणात्मक है, यह उस मान के लिए टूट जाता है। सौभाग्य से, यह अभी भी आधे मामलों में काम करता है, क्योंकि शून्य MIN_INT * [even number] होना चाहिए।इसके अलावा, अनंत छोरों को उत्पन्न करने के plusOneलिए -1कभी भी टूट जाता है , जिसके परिणामस्वरूप परिणाम अधिक हो जाता है। plusOneकिसी भी मूल्य के लिए ठीक काम करता है। गलतफहमी के लिए खेद है।

एक वास्तविक कोड ट्रोल के लिए +1: ऐसा लगता है कि इसे काम करना चाहिए, लेकिन यह बहुत संभावना है कि ओपी पर उड़ जाएगा और उसे पता नहीं क्यों होगा।
केविन

1
केवल शिफ्ट, XOR और AND का उपयोग करके किसी भी अतिरिक्त ऑपरेटरों के बिना इसके अलावा करना संभव है। ये सभी ++ मेरे सिर को चोट पहुँचा रहे हैं - कैरी के साथ एकल बिट ADD है (x ^ y) | ((x & y) << 1) (इस भद्दे छोटे टेक्स्ट बॉक्स में टाइप करने से हुई कोई भी त्रुटि।)
ऑस्टिन में जूली

@ जुलिएनस्टिन हां। एल्गोरिथ्म और भी अधिक अक्षम है जितना कि यह होना चाहिए। क्या मुझे ट्रोल सूची में संशोधन करना चाहिए? :-)
जॉन ड्वोरक

1
@ जूलीनएस्टिन (x ^ y) | ((x & y) << 1)काफी काम नहीं करता है, यह एक्स या वाई और कैरी दोनों एक ही स्थिति में सच होने पर कैरी को प्रचारित नहीं करेगा :)
हॉब्स

@hobbs समाधान: ओरिंग के बजाय, गैर-शून्य होने पर उन्हें पुन: जोड़ें।
जॉन ड्वोरक

14

फ्लोटिंग पॉइंट नंबरों के लिए भी काम करता है:

float mul(float a, float b){
  return std::exp(std::log(a) - std::log(1.0 / b));
}

11

हर कोई जानता है कि पायथन सी की तुलना में उपयोग करना आसान है और पायथन के पास प्रत्येक ऑपरेटर के अनुरूप कार्य हैं, ऐसे मामलों के लिए जहां आप ऑपरेटर का उपयोग नहीं कर सकते हैं। जो वास्तव में हमारी समस्या की परिभाषा है, है ना? इसलिए:

#include <Python.h>

void multiply(int a, int b) {
    PyObject *operator_name, *operator, *mul, *pa, *pb, *args, *result;
    int result;

    operator_name = PyString_FromString("operator");
    operator = PyImport_Import(operator_name);
    Py_DECREF(operator_name);
    mul = PyObject_GetAttrString(operator, "__mul__");
    pa = PyLong_FromLong((long)a);
    pb = PyLong_FromLong((long)b);
    args = PyTuple_New(2);
    PyTuple_SetItem(args, 0, pa);
    PyTuple_SetItem(args, 1, pb);
    presult = PyObject_CallObject(mul, args);
    Py_DECREF(args);
    Py_DECREF(mul);
    Py_DECREF(operator);
    result = (int)PyLong_AsLong(presult);
    Py_DECREF(presult);
    return result;
}

int main(int argc, char *argv[]) {
    int c;
    Py_Initialize();
    c = multiply(2, 3);
    printf("2 * 3 = %d\n", c);
    Py_Finalize();
}

10

अन्य उत्तरों में से कोई भी सैद्धांतिक रूप से ध्वनि नहीं है। जैसा कि इस सवाल पर पहली टिप्पणी कहते हैं:

कृपया "संख्या" के बारे में और अधिक विशिष्ट बनें

हमें उत्तर देने से पहले गुणन और संख्याओं को परिभाषित करना होगा। एक बार जब हम करते हैं, समस्या तुच्छ हो जाती है।

गणितीय तर्कशास्त्र की शुरुआत में ऐसा करने का सबसे लोकप्रिय तरीका ZF सेट सिद्धांत के शीर्ष पर वॉन न्यूमैन अध्यादेशों का निर्माण करना है , और फिर पीनो एक्सिओम्स का उपयोग करना है ।

यह स्वाभाविक रूप से सी में अनुवाद करता है, यह मानते हुए कि आपके पास एक सेट प्रकार है जिसमें अन्य सेट हो सकते हैं। इसमें कुछ भी शामिल नहीं है, लेकिन सेट है, जो इसे तुच्छ बनाता है ( void*अधिकांश सेट लाइब्रेरी में कोई भी कास्टिंग बकवास नहीं है ), इसलिए मैं पाठक के लिए एक अभ्यास के रूप में कार्यान्वयन को छोड़ दूंगा।

तो, पहले:

/* The empty set is 0. */
set_t zero() {
    return set_new();
}

/* The successor of n is n U {n}. */
set_t successor(set_t n) {
    set_t result = set_copy(n);
    set_t set_of_n = set_new();
    set_add(set_of_n, n);
    set_union(result, set_of_n);
    set_free(set_of_n);
    return result;
}

/* It is an error to call this on 0, which will be reported by
   running out of memory. */
set_t predecessor(set_t n) {
    set_t pred = zero();
    while (1) {
        set_t next = successor(pred);
        if (set_equal(next, n)) {
            set_free(next);
            return pred;
        }
        set_free(pred);
    }
}        

set_t add(set_t a, set_t b) {
    if (set_empty(b)) {
        /* a + 0 = a */
        return a;
    } else {
        /* a + successor(b) = successor(a+b) */
        set_t pred_b = predecessor(b)
        set_t pred_ab = add(a, pred_b);
        set_t result = successor(pred_ab);
        set_free(pred_b);
        set_free(pred_ab);
        return result;
    }
}

set_t multiply(set_t a, set_t b) {
    if (set_empty(b)) {
        /* a * 0 = 0 */
        return b;
    } else {
        /* a * successor(b) = a + (a * b) */
        set_t pred_b = predecessor(b)
        set_t pred_ab = mul(a, pred_b);
        set_t result = successor(pred_ab);
        set_free(pred_b);
        set_free(pred_ab);
        return result;
    }
}

यदि आप इसे पूर्णांकों, तर्कसंगत, वास्तविक, अतियथार्थवाद आदि के लिए विस्तारित करना चाहते हैं, तो आप बूट करने के लिए अनंत परिशुद्धता (मान लें कि आपके पास अनंत स्मृति और सीपीयू) हैं। लेकिन जैसा कि क्रॉइनेकर ने कहा, भगवान ने प्राकृतिक संख्याएं बनाईं; बाकी सब आदमी का काम है, तो वास्तव में, परेशान क्यों हो?


1
वाह। तुम मुझसे भी धीमी हो।
जॉन ड्वोरक

10
unsigned add( unsigned a, unsigned b )
{
    return (unsigned)&((char*)a)[b];  // ignore compiler warnings
       // (if pointers are bigger than unsigned). it still works.
}
unsigned umul( unsigned a, unsigned b )
{
    unsigned res = 0;
    while( a != 0 ){
        if( a & 1) res = add( res, b );
        b <<= 1;
        a >>= 1;
    }
    return res;
}

int mul( int a, int b ){
    return (int)umul( (unsigned)a, (unsigned)b );
}

अगर आप एक [b] हैक को धोखा मानते हैं (क्योंकि यह वास्तव में एक ऐड है) तो इसके बजाय यह काम करता है। लेकिन टेबल लुकअप में पॉइंटर भी शामिल है।

Http://en.wikipedia.org/wiki/IBM_1620 देखें - एक ऐसा कंम्प्यूटर जो वास्तव में लुकअप टेबलों का उपयोग करके किया ...

एक टेबल मैकेनिज्म का उपयोग करने के बारे में संतोषजनक कुछ ऐसा ऑपरेशन जो वास्तव में एक निर्देश में किया जा सकता है।

static unsigned sumtab[17][16]= {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15},
{ 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16},
{ 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17},
{ 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18},
{ 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19},
{ 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20},
{ 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21},
{ 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22},
{ 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23},
{ 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24},
{10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25},
{11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26},
{12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27},
{13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28},
{14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29},
{15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30},
{16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31}
};

unsigned add( unsigned a, unsigned b )
{
   static const int add4hack[8] =  {4,8,12,16,20,24,28,32};
   unsigned carry = 0;
   unsigned (*sumtab0)[16] = &sumtab[0];
   unsigned (*sumtab1)[16] = &sumtab[1];
   unsigned result = 0;
   int nshift = 0;
   while( (a|b) != 0 ){
      unsigned psum = (carry?sumtab1:sumtab0)[ a & 0xF ][ b & 0xF ];
      result = result | ((psum & 0xF)<<nshift);
      carry = psum >> 4;
      a = a >> 4
      b = b >> 4;
      nshift= add4hack[nshift>>2];  // add 4 to nshift.
   }
   return result;
}

उफ़, *चार है (हालाँकि यह गुणा नहीं है)
सर्ज बोर्स्च

उह, टेबल लुकअप इसके अलावा का उपयोग करता है - ([[i]) (* (a + i)) के समान है।
जूली ऑस्टिन में

@ जूलीनएस्टीन मैंने उस का उल्लेख किया है। टेबल लुकअप बिना जोड़े के किया जा सकता है, फ़ील्ड्स को मर्ज करके (जैसा कि IBM 1620 में सचित्र है, लिंक देखें) लेकिन यह सी में सेट करने के लिए गड़बड़ है - एक चीज़ के लिए आपको टेबल को एक उचित पते पर संरेखित करने की आवश्यकता है ताकि सूचकांक हो सकें बस या में हूँ।
greggo

8

मुझे यकीन है कि क्या गठन "धोखा दे" इन "कोड ट्रोल" पोस्ट में नहीं कर रहा हूँ, लेकिन यह 2 मनमाना पूर्णांक गुणा करता है, रन टाइम पर, कोई साथ *या +ऑपरेटर मानक पुस्तकालयों (C99) का उपयोग कर।

#include <math.h>
main()
{
  int a = 6;
  int b = 7;
  return fma(a,b,0);
}

8

मेरा ट्रोल समाधान unsigned int:

#include<stdio.h>

unsigned int add(unsigned int x, unsigned int y)
{
  /* An addition of one bit corresponds to the both following logical operations
     for bit result and carry:
        r     = x xor y xor c_in
        c_out = (x and y) or (x and c_in) or (y and c_in)
     However, since we dealing not with bits but words, we have to loop till
     the carry word is stable
  */
  unsigned int t,c=0;
  do {
    t = c;
    c = (x & y) | (x & c) | (y & c);
    c <<= 1;
  } while (c!=t);
  return x^y^c;
}

unsigned int mult(unsigned int x,unsigned int y)
{
  /* Paper and pencil method for binary positional notation:
     multiply a factor by one (=copy) or zero
     depending on others factor actual digit at position, and  shift 
     through each position; adding up */
  unsigned int r=0;
  while (y != 0) {
    if (y & 1) r = add(r,x);
    y>>=1;
    x<<=1;
  }
  return r;
}

int main(int c, char** param)
{
  unsigned int x,y;
  if (c!=3) {
     printf("Fuck!\n");
     return 1;
  }
  sscanf(param[1],"%ud",&x);
  sscanf(param[2],"%ud",&y);
  printf("%d\n", mult(x,y));
  return 0;
}

1
+1 मूल्यांकन मूल्यांकन का अच्छा कार्यान्वयन। मुझे आपका कोड पसंद है :)
yo '

@ B @овиЈ: मेरी गलती, मुझे लगा कि ट्रोलिंग अंडरस्टैंडिंग नहीं है। नाम बदले गए और टिप्पणियां जोड़ी गईं।
मथायस

माफ़ करना। मैंने गलत समझा कि टैग क्या है, और क्यू वास्तव में क्या है। आपको इसे वापस करना चाहिए
Bћовић

@ मैथियास इस मामले में यह समझने के लिए उपयोगी है कि यह कैसे काम करता है ताकि हम सराहना कर सकें कि कन्वर्सेशन-कैरी ऑपरेशन कितना ट्विस्टेड है। एक वास्तविक कोड-ट्रोल स्थिति में टिप्पणियों को फिर से
प्रसारित

मैं यह बताना चाहता हूं कि यदि आप बिट-उलट संख्या (हाई टू लो कैरी प्रॉप) को जोड़ना चाहते हैं और आपके पास 'बिट्रेव' निर्देश नहीं है, तो यह संभवतः एक पूरी तरह से उचित दृष्टिकोण है (सी में बदलने के बाद) > = 1 का कोर्स)
greggo

7

यहाँ बहुत सारे अच्छे उत्तर हैं, लेकिन ऐसा नहीं लगता कि उनमें से कई इस तथ्य का लाभ उठाते हैं कि आधुनिक कंप्यूटर वास्तव में शक्तिशाली हैं। अधिकांश सीपीयू में कई प्रसंस्करण इकाइयाँ होती हैं, इसलिए सिर्फ एक का उपयोग क्यों करें? हम शानदार प्रदर्शन परिणाम प्राप्त करने के लिए इसका फायदा उठा सकते हैं।

#include <stdio.h>
#include <limits.h>
#include "omp.h"

int mult(int a, int b);

void main(){
        int first;
        int second;
        scanf("%i %i", &first, &second);
        printf("%i x %i = %i\n", first, second, mult(first,second));
}

int mult(int second, int first){
        int answer = INT_MAX;
        omp_set_num_threads(second);
        #pragma omp parallel
        for(second = first; second > 0; second--) answer--;
        return INT_MAX - answer;
}

यहाँ इसके उपयोग का एक उदाहरण है:

$ ./multiply
5 6
5 x 6 = 30

#pragma omp parallelनिर्देश OpenMP एक अलग निष्पादन इकाई के लिए पाश के लिए के प्रत्येक भाग को विभाजित करता है, तो हम समानांतर में गुणा कर रहे हैं!

ध्यान दें कि आपको -fopenmpOpenMP का उपयोग करने के लिए संकलक को बताने के लिए ध्वज का उपयोग करना होगा।


ट्रोल भागों:

  1. समानांतर प्रोग्रामिंग के उपयोग के बारे में भ्रामक।
  2. नकारात्मक (या बड़े) संख्याओं पर काम नहीं करता है।
  3. वास्तव में forलूप के हिस्सों को विभाजित नहीं करता है - प्रत्येक थ्रेड लूप चलाता है।
  4. चर नाम और चर का पुनः प्रयोग करना।
  5. पर एक सूक्ष्म दौड़ की स्थिति है answer--; अधिकांश समय, यह दिखाई नहीं देगा, लेकिन कभी-कभी यह गलत परिणाम देगा।

2
पॉल आर के सिमडी उत्तर के साथ इसे क्यों नहीं मिलाएं, इसलिए आप 8x के बजाय 32x तेज चला सकते हैं? यद्यपि वास्तव में, आप GPU के साथ-साथ कोर को भी शामिल करना चाहते हैं; तब यह वास्तव में नष्ट हो जाएगा । :)

2
समानांतर में कुछ मशीनों पर इसे चलाने के लिए OpenMPI का उपयोग कर सकते हैं।
मिलिनन

6

दुर्भाग्य से, कंप्यूटर विज्ञान में गुणा एक बहुत ही कठिन समस्या है। इसके बजाय विभाजन का उपयोग करने का सबसे अच्छा समाधान है:

#include <stdio.h>
#include <limits.h>
int multiply(int x, int y) {
    int a;
    for (a=INT_MAX; a>1; a--) {
        if (a/x == y) {
            return a;
        }
    }
    for (a=-1; a>INT_MIN; a--) {
        if (a/x == y) {
            return a;
        }
    }
    return 0;
}
main (int argc, char **argv) {
    int a, b;
    if (argc > 1) a = atoi(argv[1]);
    else a = 42;
    if (argc > 2) b = atoi(argv[2]);
    else b = 13;
    printf("%d * %d is %d\n", a, b, multiply(a,b));
}

6

वास्तविक जीवन में मैं आमतौर पर ज्ञान के साथ ट्रोलिंग का जवाब देता हूं, इसलिए यहां एक जवाब है जो बिल्कुल भी ट्रोल नहीं करता है। यह सभी intमूल्यों के लिए काम करता है जहाँ तक मैं देख सकता हूँ।

int multiply (int a, int b) {
  int r = 0;
  if (a < 0) { a = -a; b = -b }

  while (a) {
    if (a&1) {
      int x = b;
      do { int y = x&r; r ^= x; x = y<<1 } while (x);
    }
    a>>=1; b<<=1;
  }
  return r;
}

यह मेरी समझ में सबसे अच्छा है, बहुत पसंद है कि कैसे एक सीपीयू वास्तव में पूर्णांक गुणा कर सकता है। सबसे पहले, हम यह सुनिश्चित करते हैं कि नकारात्मक (और नहीं, aदोनों में से किसी aएक पर हस्ताक्षर को कम से कम एक तर्क ) सकारात्मक है (और नहीं, तो मैं नकार को एक तरह के जोड़ या गुणा के रूप में गिनता हूं)। फिर while (a)लूप bहर सेट बिट के लिए परिणाम की एक स्थानांतरित प्रति जोड़ता है adoपाश लागू करता है r += xका उपयोग करने और, XOR, और क्या स्पष्ट रूप से आधा एडर का एक सेट है में स्थानांतरण, बिट्स कैरी में वापस खिलाया साथ xजब तक वहाँ कोई और अधिक (एक वास्तविक सीपीयू, जो अधिक कुशल है पूर्ण एडर का प्रयोग करेंगे रहे हैं, लेकिन सी नहीं करता ' टी के पास ऐसे ऑपरेटर होते हैं जिनकी हमें ज़रूरत होती है, जब तक कि आप +ऑपरेटर की गिनती नहीं करते हैं )।


4
पूछने वाले ने ट्रोल नहीं किया। आप ट्रोल करने वाले हैं।
जॉन ड्वोरक

2
यह एक ट्रोल ट्रोल है! गुप्त विफलता == INT_MIN पर है।
जेंडर

1
@ जेंडर हम्म। हाँ, यह एक अच्छा है। मैं अनुमान लगा रहा हूं (साधारण दो के पूरक सिस्टम पर) एक को नकारने का परिणाम अभी भी नकारात्मक है, और while(a)लूप कभी भी समाप्त नहीं होता है।
होब्स

@ हाँ, हाँ, यह मेरे लिए सही लगता है। अन्यथा बहुत सुंदर उत्तर।
जेंडर

6
 int bogomul(int A, int B)
{
    int C = 0;
    while(C/A != B)
    {

        print("Answer isn't: %d", C);
        C = rand();

    }
    return C;
}

1
यदि परिणाम ओवरफ्लो होता है तो यह बुरी तरह से विफल हो जाएगा। अच्छा! मुझे लगता है कि आपको प्रिंट नहीं करना चाहिए, हालांकि।
जॉन ड्वोरक

2
a = 2, b = 2, c = 5
Bћови

@ B @овиЈ while(C/A != B || C%A):?
abarnert

2
ध्यान दें कि यह वास्तव में डीप थॉट्स के उत्तराधिकारी के रूप में एक ही काम करने की कोशिश है, लेकिन संभवतः सभी ब्रह्मांडों के लिए , केवल एक के बजाय जहां उत्तर 42 है। यह बग के लिए नहीं था, तो बहुत प्रभावशाली होगा। और वोगों के मामले में त्रुटि से निपटने की कमी।
abarnert

1
कई सूत्र की जरूरत है। आप जानते हैं, इसे कुशल बनाने के लिए।
ग्रोगो

6

इस मिश्रण में फेंक:

#include <stdio.h>
#include <stdlib.h>

int mul(int a, int b)
{
        asm ("mul %2"
            : "=a" (a)
            : "%0" (a), "r" (b) : "cc"
        );
        return a;
}

int main(int argc, char *argv[])
{
        int a, b;

        a = (argc > 1) ? atoi(argv[1]) : 0;
        b = (argc > 2) ? atoi(argv[2]) : 0;

        return printf("%d x %d = %d\n", a, b, mul(a, b)) < 1;
}

जानकारी पृष्ठ से

- कोड में कुछ बेहद अस्वीकार्य या अनुचित रूप से पेश करना, जो सब कुछ फेंकने के बिना हटाया नहीं जा सकता है, ओपी के लिए पूरी तरह से बेकार जवाब देना।

- […] एक भाषा में होमवर्क करने का इरादा है कि आलसी ओपी स्वीकार्य सोच सकता है, लेकिन फिर भी उसे निराश करता है।


2
"गुणा और जोड़ ऑपरेटरों का उपयोग किए बिना"। नियमों का अच्छा झुकना - यह पूछने वाले के लिए बिल्कुल बेकार होगा :-)
जॉन ड्वोरक

2
यह वास्तव में एक सी समाधान नहीं है। इसके अलावा, यह मेरे ARM9 पर संकलित करने में विफल रहता है।
१०

1
@abarnert: एक प्रासंगिक तर्क के रूप में आपके कथन को पहचानने में विफल।
रनियम

@Sukminder: सवाल यह है कि "क्या सी प्रोग्राम लिखना संभव है ...?" इनलाइन असेंबली C. नहीं है। तथ्य यह है कि कुछ C कंपाइलर इनलाइन असेंबली भी नहीं बदल सकते हैं, इस तथ्य से अधिक कि कुछ C कंपाइलर C ++ भी कर सकते हैं या ObjC C ++ या ObjC को C कोड के रूप में गिनते हैं।
abarnert

2
@abarnert: यह एम्बेडेड कोड है जो व्यापक रूप से C कार्यक्रमों में उपयोग किया जाता है। हालांकि यह एक क्रॉस-ब्रीड है, यह तर्क दे सकता है कि यह एक सी प्रोग्राम है । यह भी प्रशंसनीय है कि ओपी इसे सी कोड के रूप में मान्यता देगा। यह स्पष्ट रूप से अजगर नहीं है, या?
रनियम

5
#include <stdio.h>
#include <stdlib.h>

int mult (int n1, int n2);
int add (int n1, int n2 );
int main (int argc, char** argv)
{
        int a,b;
        a = atoi(argv[1]);
        b = atoi(argv[2]);

        printf ("\n%i times %i is %i\n",a,b,mult(a,b));
        return 0;
}

int add (int n1, int n2 )
{
        return n1 - -n2;
}

int mult (int n1, int n2)
{
        int sum = 0;
        char s1='p', s2='p';
        if ( n1 == 0 || n2 == 0 ) return 0;
        if( n1 < 0 )
        {
                s1 = 'n';
                n1 = -n1;
        }
        if( n2 < 0 )
        {
                s2 = 'n';
                n2 = -n2;
        }
        for (int i = 1; i <= n2; i = add( i, 1 ))
        {
                sum = add(sum,  n1);
        }
        if ( s1 != s2 ) sum = -sum;
        return sum;
}

5

क्या एक सी प्रोग्राम लिखना संभव है जो गुणा और जोड़ ऑपरेटरों का उपयोग किए बिना दो संख्याओं को गुणा करता है?

ज़रूर:

void multiply() {
    printf("6 times 7 is 42\n");
}

लेकिन निश्चित रूप से यह धोखा है; जाहिर है कि वह (दो नंबर तक) सक्षम होना चाहता है?

void multiply(int a, int b) {
    int answer = 42;
    if (answer / b != a || answer % b) {
        printf("The answer is 42, so that's the wrong question.\n");
    } else {
        printf("The answer is 42, but that's probably not the right question anyway.\n");
    }
}

क्यों, यह मेरे लिए बिल्कुल स्पष्ट नहीं था!
लेविज

4

सूचक अंकगणित की तरह कोई अंकगणित नहीं है:

int f(int a, int b) {
        char x[1][b];
        return x[a] - x[0];
}

int
main(int ac, char **av) {
        printf("%d\n", f(atoi(av[1]),atoi(av[2])));
        return 0;
}

फ़ंक्शन fगुणन गुणन करता है। mainबस इसे दो तर्कों के साथ कहते हैं।
नकारात्मक संख्या के लिए भी काम करता है।


नकारात्मक a, हाँ, नकारात्मक bमुझे ऐसा नहीं लगता। लेकिन यह कई रचनात्मक तरीकों से ठीक करने योग्य है। सबसे सरल होगा sign_a ^ = sign_b, sign_b = 0.
12

@MSalters, परीक्षण और सभी साइन संयोजनों के लिए काम करता है (लिनक्स / जीसीसी के साथ)।
बदसूरत

3

सी#

मुझे लगता है कि घटाव और नकार की अनुमति नहीं है ... वैसे भी:

int mul(int a, int b)
{
    int t = 0;
    for (int i = b; i >= 1; i--) t -= -a;
    return t;
}

1
यह वास्तव में मेरे द्वारा सोचा गया समाधान है ... लेकिन देर से पार्टी में आने से मुझे पता था कि यह नीचे स्क्रॉल करने की बात है जब तक मैंने पाया कि किसी ने इसे नहीं लिखा था। फिर भी, आपको मुझसे (- 1) मिलता है।
फ्लोरिस

3

SSE इंट्रेंसिक्स के साथ (क्योंकि SIMD के साथ सब कुछ बेहतर है):

#include <stdio.h>
#include <stdlib.h>
#include <xmmintrin.h>

static float mul(float a, float b)
{
    float c;

    __m128 va = _mm_set1_ps(a);
    __m128 vb = _mm_set1_ps(b);
    __m128 vc = _mm_mul_ps(va, vb);
    _mm_store_ss(&c, vc);
    return c;
}

int main(int argc, char *argv[])
{
    if (argc > 2)
    {
        float a = atof(argv[1]);
        float b = atof(argv[2]);
        float c = mul(a, b);
        printf("%g * %g = %g\n", a, b, c);
    }
    return 0;
}

इस कार्यान्वयन का बड़ा लाभ यह है कि इसे आसानी से बिना *या +आवश्यकता के 4 समानांतर गुणा करने के लिए अनुकूलित किया जा सकता है।


मुझे नहीं लगता कि यह ट्रोलिंग है ...
जॉन ड्वोरक

वास्तव में ? मुझे लगा कि SIMD का व्यर्थ, गंभीर और वास्तुकला-विशिष्ट उपयोग इसे कोड-ट्रोलिंग के लिए योग्य बना देगा?
पॉल आर

हम्म ... सच। यह महसूस नहीं किया था कि यह वास्तुकला-विशिष्ट था।
जॉन ड्वोरक

3
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define INF 1000000

char cg[INF];

int main()
{
    int a, b;

    char bg[INF];
    memset(bg, '*', INF);

    scanf("%d%d", &a, &b);

    bg[b] = 0;

    while(a--)  
        strcat(cg, bg);

    int result;
    printf("%s%n",cg,&result);
    printf("%d\n", result);

    return 0;
}
  • केवल गुणा परिणाम के लिए काम करें <1 000 000
  • अब तक - ऑपरेटर से छुटकारा नहीं मिल सकता है, संभवतः यहां बढ़ाना
  • संख्या मुद्रित वर्णों को गिनने के लिए प्रिंटफ में% n प्रारूप विनिर्देशक का उपयोग करना (मैं इसे मुख्य रूप से अस्तित्व में% n की याद दिलाने के लिए पोस्ट कर रहा हूं, बजाय% n के स्ट्रेलेन आदि हो सकता है)
  • '*' के * b अक्षर प्रिंट करता है

अब इंतजार है 'ट्यूरिंग मशीन एमुलेशन' समाधान का।
ग्रोगो

1
जबकि strlen(cg) != aइसे खत्म करने के लिए एक बहुत ट्रोलिंग विधि है --(इसे O (N * N) बनाता है)।
12

3

शायद बहुत तेज :-(

   unsigned int add(unsigned int a, unsigned int b)
    {
        unsigned int carry;

        for (; b != 0; b = carry << 1) {
            carry = a & b;
            a ^= b;
        }
        return a;
    }

    unsigned int mul(unsigned int a, unsigned int b)
    {
        unsigned int prod = 0;

        for (; b != 0;  a <<= 1, b >>= 1) {
            if (b & 1)
                prod = add(prod, a);
        }
        return prod;
    }

1
Ungh। यह ट्रोलिंग नहीं है। ऐसा करने के लिए यह पूरी तरह से उचित तरीका है।
जॉन ड्वोरक

1
यह ट्राली है क्योंकि यह बहुत तेज़ है :-)
टिमटेक

3

यह हास्केल संस्करण केवल नॉनजेगेटिव पूर्णांकों के साथ काम करता है, लेकिन यह उस तरीके को गुणा करता है जिस तरह से बच्चे पहले सीखते हैं। यानी, 3x4 4 चीजों के 3 समूह हैं। इस मामले में, गिने जाने वाली "चीजें" एक छड़ी पर notches ('|') हैं।

mult n m = length . concat . replicate n . replicate m $ '|'

3
int multiply(int a, int b) {
    return sizeof(char[a][b]);
}

यदि मौसम सही है, तो यह C99 में काम कर सकता है, और आपका कंपाइलर अपरिभाषित बकवास का समर्थन करता है।


3

चूंकि ओपी ने सी के लिए नहीं पूछा था , यहां (ओरेकल) एसक्यूएल में एक है!

WITH
   aa AS (
      SELECT LEVEL AS lvl 
      FROM dual
      CONNECT BY LEVEL <= &a
   ),
   bb AS (
      SELECT LEVEL AS lvl
      FROM dual
      CONNECT BY LEVEL <= &b
   )
SELECT COUNT(*) AS addition
FROM (SELECT * FROM aa UNION ALL SELECT * FROM bb);

WITH
   aa AS (
      SELECT LEVEL AS lvl 
      FROM dual
      CONNECT BY LEVEL <= &a
   ),
   bb AS (
      SELECT LEVEL AS lvl
      FROM dual
      CONNECT BY LEVEL <= &b
   )
SELECT COUNT(*) AS multiplication
FROM aa CROSS JOIN bb;

1
मेरे भगवान, यह एस से भरा है *!
पॉल आर

1
@PaRR :) लेकिन वे ऑपरेटर नहीं हैं ।
एसक्यूबी

2
int add(int a, int b) {
    return 0 - ((0 - a) - b);
}

int mul(int a, int b) {
    int m = 0;
    for (int count = b; count > 0; m = add(m, a), count = add(count, 0 - 1)) { }
    return m;
}

UD के निशान हो सकते हैं।


2
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
  int x = atoi(argv[1]);
  int y = atoi(argv[2]);
  FILE *f = fopen("m","wb");
  char *b = calloc(x, y);
  if (!f || !b || fwrite(b, x, y, f) != y) {
    puts("503 multiplication service is down for maintenance");
    return EXIT_FAILURE;
  }
  printf("%ld\n", ftell(f));
  fclose(f);
  remove("m");
  return 0;
}

परीक्षण चालन:

$ ./a.out 1 0
0
$ ./a.out 1 1
1
$ ./a.out 2 2
4
$ ./a.out 3 2
6
$ ./a.out 12 12
144
$ ./a.out 1234 1234
1522756
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.