我认为程序员应该已经实现了自己的bignum库,因此欢迎在这里。

(当然,稍后您会发现BigInteger更好,并且可以使用它,但这是宝贵的学习经验。)

(您可以在github上关注本课程的源代码。此外,我将此内容(略有修饰)重新制成了一个由14部分组成的博客系列。)

用Java创建一个简单的Big number类

那么,我们需要什么?

首先,用数字表示

基于Java给我们的数据类型。

您认为十进制转换是最复杂的部分,让我们停留在基于十进制的模式下。为了提高效率,我们将不存储真实的十进制数字,而是使用base 1 000 000 000 = 10^9 < 2^30。这适合于Java int(最大为2^31或2^32),而两个这样的数字的乘积恰好适合于Java long。

final static int BASE = 1000000000;

final static int BASE_DECIMAL_DIGITS = 9;

然后是数字数组:

private int[] digits;

我们是否将数字存储在小端或大端中,即较大的部分在前还是后?这并不重要,因此我们决定选择大端字节,因为这是人类想要阅读的方式。(目前,我们专注于非负值-稍后我们将为负数添加一个符号位。)

为了进行测试,我们添加了一个构造函数,该构造函数允许从此类int []进行初始化。

/**

* creates a DecimalBigInt based on an array of digits.

* @param digits a list of digits, each between 0 (inclusive)

*    and {@link BASE} (exclusive).

* @throws IllegalArgumentException if any digit is out of range.

*/

public DecimalBigInt(int... digits) {

for(int digit : digits) {

if(digit < 0 ||  BASE <= digit) {

throw new IllegalArgumentException("digit " + digit +

" out of range!");

}

}

this.digits = digits.clone();

}

另外,此构造函数还可以用于单个int(如果小于BASE),甚至不可以int(我们将其解释为0)。因此,我们现在可以执行以下操作:

DecimalBigInt d = new DecimalBigInt(7, 5, 2, 12345);

System.out.println(d);

这给了我们de.fencing_game.paul.examples.DecimalBigInt@6af62373,而不是那么有用。因此,我们添加了一个toString()方法:

/**

* A simple string view for debugging purposes.

* (Will be replaced later with a real decimal conversion.)

*/

public String toString() {

return "Big" + Arrays.toString(digits);

}

现在的输出是Big[7, 5, 2, 12345],这对于测试更有用,不是吗?

第二,从十进制格式转换。

我们在这里很幸运:我们的基数(10 ^ 9)是我们要从(10)转换的基数的幂。因此,我们总是有相同的(9)个十进制数字代表一个“我们的格式”数字。(当然,开始时可能少一些数字。)在下面的代码中,decimal是一个十进制数字的字符串。

int decLen = decimal.length();

int bigLen = (decLen-1) / BASE_DECIMAL_DIGITS + 1;

这个奇怪的公式是Java int的编写方式  bigLen = ceil(decLen/BASE_DECIMAL_DIGITS)。(我希望它是正确的,我们稍后将对其进行测试。)

int firstSome = decLen - (bigLen-1) * BASE_DECIMAL_DIGITS;

这是第一位十进制数字的长度,应在1到9(含)之间。

我们创建数组:

int[] digits = new int[bigLen];

循环浏览要创建的数字:

for(int i = 0; i < bigLen ; i++) {

我们的每个数字都由原始数字中的一个数字块表示:

String block =

decimal.substring(Math.max(firstSome + (i-1)*BASE_DECIMAL_DIGITS, 0),

firstSome +   i  *BASE_DECIMAL_DIGITS);

(Math.max这里是第一个较短的块在这里需要的。)现在,我们使用常规的Integer解析函数,并将结果放入数组中:

digits[i] = Integer.parseInt(block);

}

从现在创建的数组中,我们创建DecimalBigInt对象:

return new DecimalBigInt(digits);

让我们看看这是否有效:

DecimalBigInt d2 = DecimalBigInt.valueOf("12345678901234567890");

System.out.println(d2);

输出:

Big[12, 345678901, 234567890]

看起来不错:-)我们也应该用其他一些数字(长度不同)对其进行测试。

下一部分将是十进制格式,这应该更加容易。

第三,转换为十进制格式。

我们需要将每个数字输出为9个十进制数字。为此,我们可以使用Formatter支持类printf格式字符串的类。

一个简单的变体是这样的:

public String toDecimalString() {

Formatter f = new Formatter();

for(int digit : digits) {

f.format("%09d", digit);

}

return f.toString();

}

对于我们的两个数字,将返回000000007000000005000000002000012345和000000012345678901234567890。这适用于往返(即,将其馈送到valueOf方法中会得到一个等效的对象),但前导零看起来并不太好看(并且可能与八进制数产生混淆)。因此,我们需要打破我们美丽的for-each循环,并使用不同的格式字符串作为前两位。

public String toDecimalString() {

Formatter f = new Formatter();

f.format("%d", digits[0]);

for(int i = 1 ; i < digits.length; i++) {

f.format("%09d", digits[i]);

}

return f.toString();

}

加成。

让我们从加法开始,因为它很简单(以后我们可以将其中的一部分用于乘法)。

/**

* calculates the sum of this and that.

*/

public DecimalBigInt plus(DecimalBigInt that) {

...

}

我希望你能喜欢阅读,你会读的公式,从而方法名plus,minus,times来代替add,subtract,multiply。

那么,加法是如何工作的?它的工作原理与我们在学校学习到的十进制数字大于9时相同:加上相应的数字,如果对于某些数字,结果大于10(或BASE在我们的情况下),则将一位带到下一位数字。这可能会导致所得数字比原始数字多一位。

首先,我们来看一个简单的例子,即两个数字具有相同的数字位数。然后看起来就像这样:

int[] result = new int[this.digits.length];

int carry = 0;

for(int i = this.digits.length-1; i > 0; i--) {

int digSum = carry + this.digits[i] + that.digits[i];

result[i] = digSum % BASE;

carry = digSum / BASE;

}

if(carry > 0) {

int[] temp = new int[result.length + 1];

System.arraycopy(result, 0, temp, 1, result.length);

temp[0] = carry;

result = temp;

}

return new DecimalBigInt(result);

(我们从右到左移动,因此我们可以将任何溢出都带到下一位数字。如果我们决定使用Little Endian格式,这会有些漂亮。)

如果两个数字的位数不同,则会变得更加复杂。

为了使其尽可能简单,我们将其分为几种方法:

此方法将一位数字添加到数组中的元素(可能已经包含一些非零值),并将结果存储回数组中。如果有溢出,则通过递归调用将其带到下一个数字(索引少一个,而不是一个多)。这样我们可以确保数字始终保持在有效范围内。

/**

* adds one digit from the addend to the corresponding digit

* of the result.

* If there is carry, it is recursively added to the next digit

* of the result.

*/

private void addDigit(int[] result, int resultIndex,

int addendDigit)

{

int sum = result[resultIndex] + addendDigit;

result[resultIndex] = sum % BASE;

int carry = sum / BASE;

if(carry > 0) {

addDigit(result, resultIndex - 1, carry);

}

}

下一个对要添加的整个数字数组执行相同的操作:

/**

* adds all the digits from the addend array to the result array.

*/

private void addDigits(int[] result, int resultIndex,

int... addend)

{

addendIndex = addend.length - 1;

while(addendIndex >= 0) {

addDigit(result, resultIndex,

addend[addendIndex]);

addendIndex--;

resultIndex--;

}

}

现在我们可以实现我们的plus方法:

/**

* calculates the sum of this and that.

*/

public DecimalBigInt plus(DecimalBigInt that) {

int[] result = new int[Math.max(this.digits.length,

that.digits.length)+ 1];

addDigits(result, result.length-1, this.digits);

addDigits(result, result.length-1, that.digits);

// cut of leading zero, if any

if(result[0] == 0) {

result = Arrays.copyOfRange(result, 1, result.length);

}

return new DecimalBigInt(result);

}

如果可以在可能发生溢出的情况下先查看,然后再创建一个比必要的数组大的数组,我们可以在这里做得更好。

啊,一个测试:d2.plus(d2)给出Big[24, 691357802, 469135780],看起来不错。

乘法。

让我们记得回到学校时,我们如何在纸上相乘更大的数字?

123 * 123

----------

369   <== 123 * 3

246    <== 123 * 2

123     <== 123 * 1

--------

15129

因此,我们必须将第一个数字的每个数字[i]与第二个数字的每个数字[j]相乘,并将乘积加到结果的数字[i + j]中(并注意携带)。当然,这里的索引是从右开始而不是从左开始计数。 (现在,我真的希望我使用低端数字。)

由于我们两个数字的乘积可能超出的范围int,因此我们使用long乘法。

/**

* multiplies two digits and adds the product to the result array

* at the right digit-position.

*/

private void multiplyDigit(int[] result, int resultIndex,

int firstFactor, int secondFactor) {

long prod = (long)firstFactor * (long)secondFactor;

int prodDigit = (int)(prod % BASE);

int carry = (int)(prod / BASE);

addDigits(result, resultIndex, carry, prodDigit);

}

现在我们可以看到为什么我声明我的addDigits方法采用resultIndex参数了。(并且我只是将最后一个参数更改为varargs参数,以便能够在此处更好地编写。)

因此,这里是交叉乘法的方法:

private void multiplyDigits(int[] result, int resultIndex,

int[] leftFactor, int[] rightFactor) {

for(int i = 0; i < leftFactor.length; i++) {

for(int j = 0; j < rightFactor.length; j++) {

multiplyDigit(result, resultIndex - (i + j),

leftFactor[leftFactor.length-i-1],

rightFactor[rightFactor.length-j-1]);

}

}

}

我希望我的索引计算正确。如果使用小尾数表示法,那就multiplyDigit(result, resultIndex + i + j, leftFactor[i], rightFactor[j])更清楚了,不是吗?

times现在,我们的方法只需分配结果数组,调用multiplyDigits并包装结果。

/**

* returns the product {@code this × that}.

*/

public DecimalBigInt times(DecimalBigInt that) {

int[] result = new int[this.digits.length + that.digits.length];

multiplyDigits(result, result.length-1,

this.digits, that.digits);

// cut off leading zero, if any

if(result[0] == 0) {

result = Arrays.copyOfRange(result, 1, result.length);

}

return new DecimalBigInt(result);

}

对于测试,d2.times(d2)给出Big[152, 415787532, 388367501, 905199875, 19052100],这与我的Emacs calc在此处计算的结果相同。

比较方式

我们希望能够比较我们的两个对象。因此,我们实现了Comparable它的compareTo方法。

public int compareTo(DecimalBigInt that) {

如何知道我们的一个数字是否大于另一个?首先,我们比较数组的长度。由于我们注意不要引入任何前导零(是吗?),因此较长的数组应具有较大的数字。

if(this.digits.length < that.digits.length) {

return -1;

}

if (that.digits.length < this.digits.length) {

return 1;

}

如果长度相同,我们可以按元素进行比较。由于我们使用big endian(即big end首先出现),因此我们从头开始。

for(int i = 0; i < this.digits.length; i++) {

if(this.digits[i] < that.digits[i]) {

return -1;

}

if(that.digits[i] < this.digits[i]) {

return 1;

}

}

如果一切都相同,那么显然我们的数字是相同的,我们可以返回0。

return 0;

}

equals + hashCode()

每一个良好的不可变类应该实现equals()和hashCode()在合适(兼容)的方式。

对于我们的hashCode(),我们只需对数字进行求和,然后将它们乘以小质数,以确保数字切换不会产生相同的哈希码:

/**

* calculates a hashCode for this object.

*/

public int hashCode() {

int hash = 0;

for(int digit : digits) {

hash = hash * 13 + digit;

}

return hash;

}

在该equals()方法中,我们可以简单地委托给compareTo方法,而不必再次实现相同的算法:

/**

* compares this object with another object for equality.

* A DecimalBigInt is equal to another object only if this other

* object is also a DecimalBigInt and both represent the same

* natural number.

*/

public boolean equals(Object o) {

return o instanceof DecimalBigInt &&

this.compareTo((DecimalBigInt)o) == 0;

}

所以,今天足够了。减法(可能是负数)和除法更加复杂,因此我暂时将其省略。要计算90的阶乘,就足够了。

计算大阶乘:

这里的阶乘函数:

/**

* calculates the factorial of an int number.

* This uses a simple iterative loop.

*/

public static DecimalBigInt factorial(int n) {

DecimalBigInt fac = new DecimalBigInt(1);

for(int i = 2; i <= n; i++) {

fac = fac.times(new DecimalBigInt(i));

}

return fac;

}

这给了我们

fac(90) = 1485715964481761497309522733620825737885569961284688766942216863704985393094065876545992131370884059645617234469978112000000000000000000000

从任意基数表示形式转换

在下一个frodosamoa问题的提示下,我写了关于如何从任意(位置)数字系统转换为我们(或想要)进行计算的答案。(在该示例中,我从三进制转换为十进制,而问题是从十进制转换为二进制。)

在这里,我们想从任意数字系统(好的,基数在2到36之间,所以我们可以用来将一位数字Character.digit()转换为整数)转换为带有基数BASE(= 1.000.000.000,但这在这里并不重要) 。

基本上,我们使用Horner方案来计算多项式的值,该数字在基数给定的点处作为系数。

sum[i=0..n] digit[i] * radix^i

可以使用以下循环计算:

value = 0;

for  i = n .. 0

value = value * radix + digit[i]

return value

由于我们的输入字符串是big-endian,因此我们不必倒数,而是可以使用简单的增强型for循环。(在Java中看起来更难看,因为我们没有运算符重载,也没有从int到DecimalBigInt类型的自动装箱。)

public static DecimalBigInt valueOf(String text, int radix) {

DecimalBigInt bigRadix = new DecimalBigInt(radix);

DecimalBigInt value = new DecimalBigInt(); // 0

for(char digit : text.toCharArray()) {

DecimalBigInt bigDigit =

new DecimalBigInt(Character.digit(digit, radix));

value = value.times(bigRadix).plus(bigDigit);

}

return value;

}

在我的实际实现中,我添加了一些错误检查(和引发异常),以确保我们确实有一个有效的数字,当然还有文档注释。

转换为任意位置系统更为复杂,因为它涉及余数和除法(按任意基数),而我们尚未实现,因此目前还没有实现。当我对分割方法有个好主意时,它将完成。(在这里我们只需要用小数(一位数字)进行除法,这可能比一般的除法更容易。)

小数除法

在学校里,我学会了长除法。这是一个小(一位数字)除数的示例,我们在德国使用的表示法(带有关于背景计算的注释,我们通常不会写),以十进制表示:

12345 : 6 = 02057     1 / 6 =  0

-0┊┊┊┊                 0 * 6 =  0

──┊┊┊┊

12┊┊┊                12 / 6 =  2

-12┊┊┊                 2 * 6 = 12

──┊┊┊

03┊┊                 3 / 6 =  0

- 0┊┊                 0 * 6 =  0

──┊┊

34┊                34 / 6 =  5

-30┊                 5 * 6 = 30

──┊

45                45 / 6 =  7

-42                 7 * 6 = 42

──

3     ==> quotient 2057, remainder 3.

当然,如果我们有本征余数运算,则不需要计算这些乘积(0、12、0、30、42)并减去它们。然后看起来像这样(当然,我们这里不需要编写操作):

12345 : 6 = 02057     1 / 6 =  0,   1 % 6 = 1

12┊┊┊                12 / 6 =  2,  12 % 6 = 0

03┊┊                 3 / 6 =  0,   3 % 6 = 3

34┊                34 / 6 =  5,  34 % 6 = 4

45                45 / 6 =  7,  45 % 6 = 3

3

==> quotient 2057, remainder 3.

如果我们用另一种格式编写的话,这看起来已经很像短除法了。

我们可以观察(并证明)以下内容:

如果我们有一个两位数的数字x,其第一位数字小于我们的除数d,x / d则它是一位数,并且x % d也是一位数字,小于d。这与归纳一起表明,我们只需要用除数除以两位数(余数)即可。

回到以BASE为基数的大数字:所有两位数字都可以用Java表示long,那里有native /和%。

/**

* does one step in the short division algorithm, i.e. divides

*  a two-digit number by a one-digit one.

*

* @param result the array to put the quotient digit in.

* @param resultIndex the index in the result array where

*             the quotient digit should be put.

* @param divident the last digit of the divident.

* @param lastRemainder the first digit of the divident (being the

*           remainder of the operation one digit to the left).

*           This must be < divisor.

* @param divisor the divisor.

* @returns the remainder of the division operation.

*/

private int divideDigit(int[] result, int resultIndex,

int divident, int lastRemainder,

int divisor) {

assert divisor < BASE;

assert lastRemainder < divisor;

long ent = divident + (long)BASE * lastRemainder;

long quot = ent / divisor;

long rem = ent % divisor;

assert quot < BASE;

assert rem < divisor;

result[resultIndex] = (int)quot;

return (int)rem;

}

现在,我们将循环调用此方法,始终将前一次调用的结果反馈为lastRemainder。

/**

* The short division algorithm, like described in

* Wikipedia's

*   article Short division.

* @param result an array where we should put the quotient digits in.

* @param resultIndex the index in the array where the highest order digit

*     should be put, the next digits will follow.

* @param divident the array with the divident's digits. (These will only

*          be read, not written to.)

* @param dividentIndex the index in the divident array where we should

*         start dividing. We will continue until the end of the array.

* @param divisor the divisor. This must be a number smaller than

*        {@link #BASE}.

* @return the remainder, which will be a number smaller than

*     {@code divisor}.

*/

private int divideDigits(int[] result, int resultIndex,

int[] divident, int dividentIndex,

int divisor) {

int remainder = 0;

for(; dividentIndex < divident.length; dividentIndex++, resultIndex++) {

remainder = divideDigit(result, resultIndex,

divident[dividentIndex],

remainder, divisor);

}

return remainder;

}

此方法仍返回一个int,其余为。

现在我们要有一个返回DecimalBigInt的公共方法,所以我们创建一个。它的任务是检查参数,为工作方法创建一个数组,丢弃其余部分并从结果中创建DecimalBigInt。(构造函数删除可能存在的前导零。)

/**

* Divides this number by a small number.

* @param divisor an integer with {@code 0 < divisor < BASE}.

* @return the integer part of the quotient, ignoring the remainder.

* @throws IllegalArgumentException if the divisor is <= 0 or >= BASE.

*/

public DecimalBigInt divideBy(int divisor)

{

if(divisor <= 0 || BASE <= divisor) {

throw new IllegalArgumentException("divisor " + divisor +

" out of range!");

}

int[] result = new int[digits.length];

divideDigits(result, 0,

digits, 0,

divisor);

return new DecimalBigInt(result);

}

我们还有一个类似的方法,它返回余数:

/**

* Divides this number by a small number, returning the remainder.

* @param divisor an integer with {@code 0 < divisor < BASE}.

* @return the remainder from the division {@code this / divisor}.

* @throws IllegalArgumentException if the divisor is <= 0 or >= BASE.

*/

public int modulo(int divisor) {

if(divisor <= 0 || BASE <= divisor) {

throw new IllegalArgumentException("divisor " + divisor +

" out of range!");

}

int[] result = new int[digits.length];

return divideDigits(result, 0,

digits, 0,

divisor);

}

这些方法可以这样调用:

DecimalBigInt d3_by_100 = d3.divideBy(100);

System.out.println("d3/100 = " + d3_by_100);

System.out.println("d3%100 = " + d3.modulo(100));

转换为任意基数

现在我们有了转换为任意基数的基础。当然,不是真正任意的,只有基数小于BASE允许的基数,但这应该不是太大的问题。

正如在有关转换数字的另一个答案中已经回答的那样,我们必须执行“除法,余数,乘法,加法”。“乘加”部分实际上只是将各个数字放在一起,因此我们可以用一个简单的数组代替它-访问。

由于我们总是需要商和余数,因此我们将不使用public方法modulo和divideBy,而是反复调用该divideDigits方法。

/**

* converts this number to an arbitrary radix.

* @param radix the target radix, {@code 1 < radix < BASE}.

* @return the digits of this number in the base-radix system,

*     in big-endian order.

*/

public int[] convertTo(int radix)

{

if(radix <= 1 || BASE <= radix) {

throw new IllegalArgumentException("radix " + radix +

" out of range!");

}

首先,对0进行特殊处理。

// zero has no digits.

if(digits.length == 0)

return new int[0];

然后,我们为结果数字(足够长)和一些其他变量创建一个数组。

// raw estimation how many output digits we will need.

// This is just enough in cases like BASE-1, and up to

// 30 digits (for base 2) too much for something like (1,0,0).

int len = (int) (Math.log(BASE) / Math.log(radix) * digits.length)+1;

int[] rDigits = new int[len];

int rIndex = len-1;

int[] current = digits;

int quotLen = digits.length;

quotLen是最后一个商的位数(不包括前导零)。如果为0,则完成。

while(quotLen > 0)  {

下一个商的新数组。

int[] quot = new int[quotLen];

商与余数运算。商现在在quot,余数在rem。

int rem = divideDigits(quot, 0,

current, current.length - quotLen,

radix);

我们将其余部分放在输出数组中(从最后一位开始填充)。

rDigits[rIndex] = rem;

rIndex --;

然后我们将数组交换到下一轮。

current = quot;

如果商中有前导零(由于基数小于BASE,最大为1),我们将商大小缩小1。下一个数组将更小。

if(current[0] == 0) {

// omit leading zeros in next round.

quotLen--;

}

}

循环之后,rDigits数组中可能有前导零,我们将其切除。

// cut of leading zeros in rDigits:

while(rIndex < 0 || rDigits[rIndex] == 0) {

rIndex++;

}

return Arrays.copyOfRange(rDigits, rIndex, rDigits.length);

}

而已。但是,它看起来有点复杂。这是一个如何使用它的示例:

System.out.println("d4 in base 11: " +

Arrays.toString(d4.convertTo(11)));

System.out.println("d5 in base 7: " +

Arrays.toString(d5.convertTo(7)));

它们打印[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0]和[1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0],与我们之前解析的数字相同(不过是从字符串中提取的)。

基于此,我们还可以将其格式化为字符串:

/**

* Converts the number to a String in a given radix.

* This uses {@link Character.digit} to convert each digit

* to one character.

* @param radix the radix to use, between {@link Character.MIN_RADIX}

*   and {@link Character.MAX_RADIX}.

* @return a String containing the digits of this number in the

*   specified radix, using '0' .. '9' and 'a' .. 'z' (as much as needed).

*/

public String toString(int radix) {

if(radix < Character.MIN_RADIX || Character.MAX_RADIX < radix) {

throw new IllegalArgumentException("radix out of range: " + radix);

}

if(digits.length == 0)

return "0";

int[] rdigits = convertTo(radix);

StringBuilder b = new StringBuilder(rdigits.length);

for(int dig : rdigits) {

b.append(Character.forDigit(dig, radix));

}

return b.toString();

}

java biginteger转int_如何在不使用java.math.BigInteger的情况下使用Java处理非常大的数字...相关推荐

  1. java没有对象可以调用方法吗_在没有括号的情况下调用Java中的新对象的方法:操作顺序违规?...

    这是因为Java语言的定义如何.运算符的优先级只有在两种不同的方式解析相同的词法序列时才起作用,但事实并非如此. 为什么? 因为分配在 Primary: ... new Creator 而方法调用定义 ...

  2. Java不用main方法运行_如何在不定义main方法的情况下运行Java程序?

    我正在查看一些Java源代码,并注意到main方法没有定义. Java如何编译源代码而不知道从哪里开始? main方法仅在Java虚拟机执行代码时使用.没有main方法就无法执行代码,但仍然可以编译代 ...

  3. java中数组的内存模型_Java如何在内存有限的情况下实现一个超大数组?jvm性能调优+内存模型+虚拟机原理能解决什么样问题...

    在上一篇文章中,小编为您详细介绍了关于<变频器调速问题?三星R458更换CPU>相关知识.本篇中小编将再为您讲解标题Java如何在内存有限的情况下实现一个超大数组?jvm性能调优+内存模型 ...

  4. 不安全的发布 java_如何在没有安全警告的情况下发布Java Web S...

    我有一个从网站的jnlp文件启动的Java应用程序.我试图让它运行而不会在它运行之前闪烁一堆安全警告. 该程序分为大约10个不同的jar文件,30个左右的jar库,以及jar文件中还包含的几个本机库. ...

  5. Java实现给图片局部打马赛克(前提是知道坐标的情况下)

    直接上代码 package com.test;/*** 图片区域类* @author hty**/ public class ImageArea {int x; //指定区域左上角横坐标int y; ...

  6. java 隐藏参数,如何在没有JVM参数的情况下隐藏java 9中的“...

    有一些方法可以禁用非法访问警告,但我不建议这样做. 1.简单的方法 由于警告打印到默认错误流,您只需关闭此流并将stderr重定向到stdout. public static void disable ...

  7. java 浏览器设置字体大小_Sass可以在不使用REM的情况下访问浏览器的默认字体大小吗?...

    有没有办法从Sass中访问浏览器的默认字体大小设置但不使用REM? 情况:我正在设置Sass函数和mixins,这将让我使用基于rem的垂直基线网格(垂直节奏,如果你愿意的话) . 使用REM我可以将 ...

  8. java查询数据库大批量数据_数据库有百万数据量的情况下,分页查询的方法及其优化方式...

    当需要从数据库查询的表有上万条记录的时候,一次性查询所有结果会变得很慢,特别是随着数据量的增加特别明显,这时需要使用分页查询.对于数据库分页查询,也有很多种方法和优化的点. 下面简单说一下我知道的一些 ...

  9. java编译报错提示编码gbk的不可映射字符啥意思_解决java编译错误:编码GBK的不可映射字符...

    [我的Android进阶之旅]解决Android Studio 运行gradle命令时报错: 错误: 编码GBK的不可映射字符 1.问题描述 最近在负责公司基础业务和移动基础设施的开发工作,正在负责L ...

最新文章

  1. 【c语言】蓝桥杯基础练习 01字串
  2. Ubuntu18.04安装Dlib-19.19.0成功
  3. Hiveduino编程电子积木平台产品介绍宣传视频
  4. OSI七层模型详解-开放系统互联参考模型详解
  5. 短视频自媒体成功的秘诀就一个字:真
  6. Spark on Yarn查看删除日志
  7. Python build-in数据类型之字符串str (一)
  8. c语言中开方,C++_详细解析C语言中的开方实现,关于C语言中的开方计算,首先 - phpStudy...
  9. 大数据平台建设实施方案
  10. excel打开html非常慢,打开excel很慢
  11. WPF随笔(四)--窗口多屏显示及全屏
  12. sh股票是什么意思?
  13. 【转载】超简单集成HMS ML Kit 人脸检测实现可爱2D贴纸
  14. java 拉姆达 lamdba get
  15. Wide Deep模型的理解及实战(Tensorflow)
  16. Android——仿京东秒杀
  17. IEC61850开发,smv9-1测试工具
  18. np.atleast_2d用法
  19. 轮播与fragment联动
  20. 万年历查询java项目查询,Java日历查询程序(万年历)

热门文章

  1. Python学习笔记:面向对象编程(2)
  2. CUDA Stream流并发性
  3. 【Leetcode】Python 代码本地构造二叉树、链表
  4. 【Python】sort 和 sorted 的用法区别
  5. 【比赛】论如何七天内在研究生电子设计竞赛中拿国奖
  6. [云炬创业基础笔记]第一章创业环境测试10
  7. [NTU-Machine-learning-note]1 Introduction(4)
  8. The greatest happiness 2019-11-13
  9. fpga芯片架构设计与实现 pdf_FPGA设计的8大重要知识点,你都get了吗
  10. Redis介绍及常用应用场景介绍