簡體   English   中英

找到非零整數x,其中x == -x?

[英]Finding a nonzero integer x where x == -x?

在我大學的算法和數據結構課程中,我收到了這個問題:

哪個整數與其負值具有相同的位模式?

意思是:x == -x

我知道0有效,但我懷疑教練正在尋找其他數字x。 它是什么x? 你怎么會找到它?

Integer.MIN_VALUE和Long.MIN_VALUE沒有等效的正值,當你取這些值的負值時,你會得到相同的值。

負與翻轉所有位並添加一個相同。

-x = ~x + 1

所以-0x80000000 = 0x7fffffff + 1 = 0x8000000

注意:Math.abs(Integer.MIN_VALUE)== Integer.MIN_VALUE為負數。 這個方法的javadoc概述了這一點。

從技術上講,有很多答案和類型

byte x = 0;
short x = 0;
char x = 0;
int x = 0;
int x = Integer.MIN_VALUE;
float x = 0.0f;
float x = -0.0f;
long x = 0;
long x = Long.MIN_VALUE;
double x = 0.0;
double x = -0.0;
Byte x = 0;
Short x = 0;
Character x = 0;
Integer x = 0;
Integer x = Integer.MIN_VALUE;
Float x = 0.0f;
Float x = -0.0f;
Long x = 0L;
Long x = Long.MIN_VALUE;
Double x = 0.0;
Double x = -0.0;

類似的Java Puzzler是; 以下表達式何時為true

x != x + 0

編輯:浮點數同時為+0.0-0.0 這樣你可以考慮-0.00.0的不同值,盡管是-0.0 == -(-0.0)

注意: Double.compare(0.0, -0.0) > 0注意:

假設您采用帶符號二進制補碼格式的最低可表示數字。 假設這個數字(稱之為x)具有位模式100000...0 ,例如。 要計算-x,首先將所有位翻轉到01111...1 ,然后再加1。 這會導致較大的紋波進位導致數字1000....0 ,這是您開始使用的數字。 因此,您將擁有x == -x 在Java int的情況下,此值為Integer.MIN_VALUE ,即-2 31

你可以用數學方法解決這個問題。 由於有符號二進制補碼格式的所有數字都以兩個冪(例如,2 d )的模數表示,因此該語句

x == -x

真正意思

x == -x(mod 2 d

這意味着

2x == 0(mod 2 d

因此,該問題的解決方案是所有數字x的集合,其中2x是0 mod 2 d 這些是任何整數k的形式k× 2d的數字。 這些值中只有兩個可以用帶符號的二進制補碼格式表示,其中d + 1位,即0和-2 d 因此,最小可能的負數將始終與其負值相等。

希望這可以幫助!

對於8位整數: 1000 0000簽名,這是-128而無符號時這是128

另一種方式:所有已簽名的原始整數類型表示范圍內的整數

-2 N-1至2 N-1 -1

(包括),其中N是位數。 每當執行任何數學整數運算時,如果數學結果是某個數字Z超出該范圍(“溢出”),那么實際結果將是R = Z + 2 N * k,其中k是某個正整數或負整數選擇使得R將在-2 N-1到2 N-1 -1的范圍內。所以說x = -2 N-1 ,我們計算-x。 數學結果是Z = 2 N-1 ,但是這超出了范圍,因為Z> 2 N-1 -1。 因此,要使其在范圍內,我們需要為某些k添加2 N * k,並且k必須為-1。 因此,實際結果是R = 2 N-1 +(2 N )*( - 1)= 2 N-1 -2 N = -2 N-1 ,這是x的原始值。 所以這是一個使x == -x的值。

Java只簽署了整數類型,但在具有無符號類型的語言中,無符號類型的范圍是0到2 N -1(包括0和2 N -1)。 但其他一切都以同樣的方式適用。

如上所述,問題含糊不清。

0當然是顯而易見的解決方案,正如其他人所討論的那樣,Java中沒有其他解決方案(問題是如何被標記的)。

在C中,對於任何有符號整數類型,給定類型的最小值可以某些實現的解決方案。 例如,給定2的補碼表示,評估-INT_MIN 可能會給你-INT_MIN 但事實上,即使你假設2的補碼,由於溢出,評估該表達式的行為也是未定義的 (環繞語義很常見,但不保證。)此外,C標准不需要二進制補碼表示; 它還允許1的補碼和符號和幅度,這兩者都沒有額外的負值。

這個程序:

#include <stdio.h>
#include <limits.h>
int main(void) {
    int n = INT_MIN;
    printf("%d\n%d\n", n, -n); /* Warning: Undefined behavior for -n */
}

在我的系統上生成此輸出:

-2147483648
-2147483648

C無符號類型的操作具有更嚴格定義的行為。 這個程序:

#include <stdio.h>
#include <limits.h>
int main(void) {
    unsigned int n = UINT_MAX / 2 + 1;
    printf("%u\n%u\n", n, -n);
}

在具有32位int (並且沒有填充位)的系統上提供此輸出:

2147483648
2147483648

並將在任何符合要求的實現上打印兩行相同的輸出。

C ++在此區域中具有與C相同的行為(或未定義的行為)。

在Perl中,如果一個大整數太大而不能表示為一個整數,那么它將落在一個浮點表示中 - 但Perl標量很復雜,並且可以同時存儲多個表示。 在我的64位系統上,這個Perl程序:

#!/usr/bin/perl

use strict;
use warnings;

my $n = -2.0**63;
print $n, "\n", -$n, "\n";
printf "%d\n%d\n", $n, -$n;

給出這個輸出:

-9.22337203685478e+18
9.22337203685478e+18
-9223372036854775808
-9223372036854775808

我不完全確定我能解釋自己。

Python似乎回退到某種形式的擴展精度整數,因此不會出現溢出問題,因此沒有數值是它自己的否定。 許多其他語言(包括,我認為,大多數Lisp方言)都做同樣的事情。

在Ada中,整數溢出沒有未定義的行為; 需要提出異常。 這個程序:

with Ada.Text_IO; use Ada.Text_IO;
procedure Foo is
    N: Integer := Integer'First;
begin
    Put_Line(Integer'Image(N));
    Put_Line(Integer'Image(-N));
end Foo;

只產生一行輸出:

-2147483648

然后死於Constraint_Error異常。

等等,等等......

因此,除非教師只是尋找零作為答案,否則它在很大程度上取決於上下文。

看看這個問題,為什么你會假設0 (這是一個完全正確和明顯的答案,如同所寫的問題,顯然是Java中唯一正確的答案)不是教師所尋求的?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM