0

I have two numbers which are 32 digit decimal floating point numbers, like 1.2345678901234567890123456789012, I want to get the multiplication which is also 32 digit decimal floating point number. Is there any efficient way to do this?

  • 4
    Take a look at Boost.Multiprecision – Paul Floyd Jun 30 '17 at 08:01
  • 1
    Are you talking about accurate decimal representation of 32 digits or is it just some more-or-less accurate value? Start with, how you store a 32 digit value, only when this works worry about math operations. – grek40 Jun 30 '17 at 08:01
  • I store a 32 digit value by four int numbers (8 digit per number), but it seems a bad way to do the multiplication – neverflow Jun 30 '17 at 08:10
  • The numbers you mention are not floating-point unless you have a decimal floating-point implementation, in which case you don't have a question. They are decimal numbers with fractions. – user207421 Jun 30 '17 at 08:13
  • I think the question ask for the accurate value – neverflow Jun 30 '17 at 08:17
  • Thanks! But this one is a past exam question, I think Boost is not allowed . – neverflow Jun 30 '17 at 08:20
  • For example I have two numbers that are 12345678901234567890123456789012 02, 02 represents 10^2, I want to get the accurate multiplication of the two 32 digit big number. – neverflow Jun 30 '17 at 08:24
  • One approach is double-double arithmetic, that is chaining together two IEEE double-precision floating-point numbers with adjacent exponents to form a single >32-digit number. See for instance [Library for Double-Double and Quad-Double Arithmetic](https://www.jaist.ac.jp/~s1410018/papers/qd.pdf) which describes the multiplication algorithm. – doynax Jun 30 '17 at 09:02
  • take a look at [Fast bignum square computation](https://stackoverflow.com/q/18465326/2521214) and try karatsuba ...Also this [Building a logarithm function in C without using float type](https://stackoverflow.com/a/42108287/2521214) might help see the `fx32_mul` implementation without asm at the end to see how to multiply without overflow. – Spektre Jun 30 '17 at 21:58

2 Answers2

1

Just use boost::multiprecision. You can use arbitrary precision but there is a typedef cpp_bin_float_50 which is a float with 50 decimal places.

Example for multiplying to big decimal numbers:

#include <iostream>
#include <boost/multiprecision/cpp_bin_float.hpp>

int main(){
  boost::multiprecision::cpp_bin_float_50 val1("1.2345678901234567890123456789012");
  boost::multiprecision::cpp_bin_float_50 val2("2.2345678901234567890123456789012");  
  std::cout <<  std::setprecision(std::numeric_limits< boost::multiprecision::cpp_bin_float_50>::max_digits10);
  std::cout << val1*val2 << std::endl;
}

Output:

2.7587257654473404640618808351577828416864868162811293
Ari Hietanen
  • 1,749
  • 13
  • 15
0

Use the usual grade school algorithm (long multiplication). If you used 3 ints (instead of 4):

A2A1A0 * B2B1B0 = A2*B2 A2*B1 A2*B0
                        A1*B2 A1*B1 A1*B0
                              A0*B2 A0*B1 A0*B0

Every multiplication will have a 2-int result. You have to sum every column on the right side, and propagate carry. In the end, you'll have a 6-int result (if inputs are 4-int, then the result is 8-int). You can then round this 8-int result. This is how you can handle the mantissa part. The exponents should just be added together.

I recommend you to divide a problem into two parts:

  1. multiplying a long number with an int
  2. adding the result from 1. into the final result

You'll need something like this as a workhorse (note that this code assumes that int is 32-bit, long long is 64-bit):

void wideMul(unsigned int &hi, unsigned int &lo, unsigned int a, unsigned int b) {
    unsigned long long int r = (unsigned long long int)a*b;
    lo = (unsigned int)r;
    hi = (unsigned int)(r>>32);
}

Note: that if you had larger numbers, there are faster algorithms.

geza
  • 28,403
  • 6
  • 61
  • 135
  • Thanks for your answer! But I think you couldn't do A0*B0 as the result is larger than the maximum int value (overflow). – neverflow Jun 30 '17 at 09:01
  • The hard point is that even I divide the big number into 4 ints, it is still big to do the multiplication and to store the result, same as long or long long. – neverflow Jun 30 '17 at 09:03
  • @neverflow: yes, you need to handle overflow. You can use `long long unsigned int` for that. All the compilers I know, `long long int` has twice as many bits as int has (that's what I meant "2-int result") – geza Jun 30 '17 at 09:08