如何在 Java 中将非常大的十进制数转换为二进制数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5372279/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 10:48:27  来源:igfitidea点击:

How Can I Convert Very Large Decimal Numbers to Binary In Java

javabinarydecimal

提问by frodosamoa

For instance, How would I be able to convert 2^60or 12345678901234567890123456789012345678901234567890to binary? Basically, numbers that are too large to represent in Java.

例如,我如何能够转换2^6012345678901234567890123456789012345678901234567890二进制?基本上,太大而无法在 Java 中表示的数字。

Edit: I will be making a class that will be able to represent number that are too large. I'm just having a hard time figuring our how to convert decimal to binary.

编辑:我将制作一个能够表示过大数字的类。我只是很难弄清楚我们如何将十进制转换为二进制。

Edit2: And also, I am not allowed to use BigDecimal, BigInteger, or any other library, sorry for not specifying earlier.

Edit2:而且,我不允许使用 BigDecimal、BigInteger 或任何其他库,抱歉没有提前指定。

回答by Pa?lo Ebermann

Try this:

试试这个:

new BigDecimal("12345678901234567890123456789012345678901234567890").toString(2);


Edit:

编辑:

For making a big-number class, you may want to have a look at my post about this a week ago. Ah, the question was by you, never mind.

为了制作一个大数字类,你可能想看看我一周前关于这个的帖子。啊,问题是你的,没关系。

The conversion between different number systems in principle is a repeated "division, remainder, multiply, add" operation. Let's look at an example:

不同数系之间的转换原则上是重复的“除、余、乘、加”运算。让我们看一个例子:

We want to convert 123 from decimal to a base 3 number. What do we do?

我们想将 123 从十进制转换为基数为 3 的数字。我们做什么?

  1. Take the remainder modulo 3 - prepend this digit to the result.
  2. Divide by 3.
  3. If the number is bigger than 0, continue with this number at step 1
  1. 取余数模 3 - 将此数字添加到结果中。
  2. 除以 3。
  3. 如果数字大于 0,则在步骤 1 中继续使用此数字

So it looks like this:

所以它看起来像这样:

  • 123 % 3 == 0. ==> The last digit is 0.
  • 123 / 3 == 41.
  • 41 % 3 == 2==> The second last digit is 2.
  • 41 / 3 == 13
  • 13 % 3 == 1==> The third digit is 1.
  • 13 / 3 == 4
  • 4 % 3 == 1==> The fourth digit is 1again.
  • 4 / 3 == 1
  • 1 % 3 == 1==> The fifth digit is 1.
  • 123 % 3 == 0. ==> 最后一位是0.
  • 123 / 3 == 41.
  • 41 % 3 == 2==>倒数第二个数字是2
  • 41 / 3 == 13
  • 13 % 3 == 1==> 第三个数字是1
  • 13 / 3 == 4
  • 4 % 3 == 1==>1又是第四位。
  • 4 / 3 == 1
  • 1 % 3 == 1==>第五位数字是1

So, we have 11120as the result.

所以,我们得到11120了结果。

The problem is that for this you need to have already some kind of division by 3 in decimal format, which is usually not the case if you don't implement your number in a decimal-based format (like I did in the answer to your last question linked above).

问题是,为此,您需要以十进制格式进行某种除以 3,如果您不以基于十进制的格式实现您的数字,通常情况并非如此(就像我在对您的回答中所做的那样)上面链接的最后一个问题)。

But it works for converting from your internal number format to any external format.

但它适用于从您的内部数字格式转换为任何外部格式。



So, let's look at how we would do the inverse calculation, from 11120(base 3) to its decimal equivalent. (Base 3 is here the placeholder for an arbitrary radix, Base 10 the placeholder for your internal radix.) In principle, this number can be written as this:

所以,让我们看看我们将如何进行逆计算,从11120(基数 3)到十进制等价物。(这里的基数 3 是任意基数的占位符,基数 10 是内部基数的占位符。)原则上,这个数字可以写成这样:

1 * 3^4 + 1 * 3^3 + 1*3^2 + 2*3^1 + 0*3^0

A better way (faster to calculate) is this:

更好的方法(计算速度更快)是这样的:

((((1 * 3) + 1 )*3 + 1 )*3 + 2)*3 + 0
    1
        3
             4
                12
                    13
                        39
                            41
                              123
                                  123

(This is known as Horner scheme, normally used for calculating values of polynomials.)

(这被称为霍纳方案,通常用于计算多项式的值。)

You can implement this in the number scheme you are implementing, if you know how to represent the input radix (and the digits) in your target system.

如果您知道如何在目标系统中表示输入基数(和数字),则可以在您正在实现的数字方案中实现这一点。

(I just addedsuch a calculation to my DecimalBigInt class, but you may want to do the calculations directly in your internal data structure instead of creating a new object (or even two) of your BigNumber class for every decimal digit to be input.)

(我刚刚在我的 DecimalBigInt 类中添加了这样的计算,但您可能希望直接在内部数据结构中进行计算,而不是为要输入的每个十进制数字创建一个 BigNumber 类的新对象(甚至两个)。)

回答by Pew

Here is a quik&dirty(very very very dirty) code:

这是一个 quik& dirty(非常非常非常脏)的代码:

public class BigDec2Bin {

    public static int[] string2arrayReversed( String s )
    {
        char a[] = s.toCharArray();
        int  b[] = new int[ s.length() ];
        for( int i = 0; i < a.length; i++ )
        {
            b[a.length-1-i] = a[i] - 48;
        }
        return b;
    }

    // adds two binary numbers represented as strings
    public static String add( String s1, String s2 )
    {
        String result = "", stmp;
        int[] a1, a2;
        int ctmp, mark = 0;

        // a1 should be the longer one
        a1 = string2arrayReversed( ( s1.length() > s2.length() ? s1 : s2 ) );
        a2 = string2arrayReversed( ( s1.length() < s2.length() ? s1 : s2 ) );

        for( int i = 0; i < a1.length; i++ )
        {
            ctmp = a1[i] + ( i < a2.length ? a2[i] : 0 ) + mark;

            switch( ctmp )
            {
                default:
                case 0:
                    stmp = "0";
                    mark = 0;
                    break;
                case 1:
                    stmp = "1";
                    mark = 0;
                    break;
                case 2:
                    stmp = "0";
                    mark = 1;
                    break;
                case 3:
                    stmp = "1";
                    mark = 1;
                    break;
            }

            result = stmp + result;
        }

        if( mark > 0 ) { result = "1" + result; }

        return result;
    }

    public static String dec2bin( String s )
    {
        String result = "";

        for( int i = 0; i < s.length() ; i++ )
        {
            result = add( result + "0", result + "000" );
            result = add( result, Integer.toBinaryString( s.charAt(i) - 48 ) );
        }

        return result;
    }

    public static void main( String[] args )
    {
        String dec = "12345"; // should be 11000000111001
        System.out.println( "dec2bin( " + dec + " ) = " + dec2bin( dec ) );

        dec = "12345678901234567890123456789012345678901234567890";
        System.out.println( "dec2bin( " + dec + " ) = " + dec2bin( dec ) );
    }

}


Output:

输出:

dec2bin( 12345 ) = 011000000111001

dec2bin( 12345678901234567890123456789012345678901234567890 ) = 10000111001001111111011000110110100110101010111110000011110010100001010100000010011001110100011110101111100011000111111100011001011011001110001111110000101011010010

dec2bin(12345)= 011000000111001

DEC2BIN(12345678901234567890123456789012345678901234567890)= 10000111001001111111011000110110100110101010111110000011110010100001010100000010011001110100011110101111100011000111111100011001011011001110001111110000101011010010



My main idea is to use always strings.

我的主要想法是始终使用字符串。

add-method adds two binary numbers which are represented as strings
dec2bin-method is where the magic happens.

add-method 将两个表示为字符串的二进制数相加
dec2bin-method 是魔法发生的地方。

Allow me to explain:

请允许我解释一下:

result = add( result + "0", result + "000" );

is a calculation to multiply any given number by 10.

是将任何给定数字乘以 10 的计算。

Multiplying a binary number by 10 is the same as adding the number with shifts:

将二进制数乘以 10 与将数字相加移位相同:

x*10 <=> x<<1 + x<<3

x*10 <=> x<<1 + x<<3

result = add( result, Integer.toBinaryString( s.charAt(i) - 48 ) );

just adds a the next digit (from left to right) on the result string

只需在结果字符串上添加下一个数字(从左到右)



Basicly what I'm doing is for example with 1234:
0*10 + 1 = 1
1*10 + 2 = 12
12*10 + 3 = 123
123*10 + 4 = 1234

基本上我正在做的是例如 1234:
0*10 + 1 = 1
1*10 + 2 = 12
12*10 + 3 = 123
123*10 + 4 = 1234

but only in binary (represented as strings).

但仅限于二进制(表示为字符串)。



I hope i could help and sorry for my bad english.

我希望我能帮上忙,并为我的英语不好而感到抱歉。

回答by meriton

What about this approach:

这种方法怎么样:

result = 0;
for each digit in the decimal number, from left to right
    result = result * 10 + digit;
return result;

So we need a way to represent an arbitrarily large binary number, and implement multiplication by 10 and addition of small numbers.

所以我们需要一种方法来表示任意大的二进制数,实现10的乘法和小数的加法。

The most straightforward way to represent an arbitrarily large binary number is an array of its binary digits. You can then apply the algorithms for addition and multiplicationyour learned in elementary school, except that digits will "overflow" when they exceed 1 rather than 9. For example:

表示任意大二进制数的最直接方式是其二进制数字的数组。然后你可以应用你在小学学到的加法和乘法算法,除了当数字超过 1 而不是 9 时,数字会“溢出”。例如:

  1010 * 1100111
----------------
        11001110 
+     1100111000
----------------
     10000000110

回答by olin

Pew: thanks, that works for some numbers. The number 6123456789012 however doesn't work, but here is the fix:

皮尤:谢谢,这适用于一些数字。然而,数字 6123456789012 不起作用,但修复方法如下:

// a1 should be the longer one
a1 = string2arrayReversed( ( s1.length() >= s2.length() ? s1 : s2 ) ); //GREATER EQUAL 

回答by pyb1993

there is a fast program to get the binary representation of a huge decimal. This programm is indeed fast, it takes only 20ms to deal with a decimal with 3000digits, eg:string(3000,'2')+'12345'. because of the pursuit of efficiency, it is not very readable. you can modify it yourself to make it easier to understand.

有一个快速程序来获得一个巨大的十进制的二进制表示。这个程序确实很快,处理一个3000位的小数只需要20ms,例如:string(3000,'2')+'12345'。因为追求效率,所以可读性不是很强。您可以自己修改它以使其更易于理解。

    inline string remove_pre_zero(const string& a)
{
    auto t = a.find_first_not_of('##代码##', 0);
    if (t == a.npos)
        return string("0");
    else
        return a.substr(t);
}

string convert_to_bin(const string& _s)
{
    const static string str[] = { "0", "1" };
    string s(_s.size(), '0');
    string binary;
    binary.reserve(_s.size()*3);
    int i = 0;
    for (const auto& c : _s)    
        s[i++] = (c - '0');

    while (s!="0")//simulate divide by 2
    {
        int t = 0, old_t = 0;
        for (auto& ch : s)
        {
            t = ((old_t * 10 + ch) & 1);
            ch = (ch + old_t * 10) >>1;
            old_t = t;
        }
        binary += str[t];
        if (s[0] == 0)
            s = remove_pre_zero(s);
    }   
        return string(binary.rbegin(), binary.rend());
}

回答by Bart van Heukelom

If you only work with integers, use BigInteger.toByteArray.

如果您只使用整数,请使用BigInteger.toByteArray

If not, unfortunately BigDecimaldoesn't have that method. But I suppose you can always (in both cases) just ASCII encode the string representation of the number, if the binary form is just meant for transfer and not calculation anywhere.

如果没有,不幸的BigDecimal是没有这种方法。但我想你总是可以(在这两种情况下)只对数字的字符串表示进行 ASCII 编码,如果二进制形式只是为了传输而不是在任何地方计算。