为什么Java不支持无符号整数呢?
在我看来,这是一个奇怪的遗漏,因为它们允许我们编写代码,这样就不太可能在异常大的输入上产生溢出。
此外,使用无符号整数可以是一种自记录的形式,因为它们表示无符号int要保存的值永远不应该是负数。
最后,在某些情况下,无符号整数对于某些操作(如除法)更有效。
把这些放进去有什么坏处?
- 我不知道,但这让我很恼火;例如,用这种方式编写网络代码要困难得多。
- 我希望语言/数据库中只有两种类型。世界:数字和字符串:)
- 编写网络代码一点也不难。btw inputstream.read()返回无符号字节,而不是有符号字节,因此网络示例是一个混淆的imho。唯一令人困惑的是,您认为编写有符号值与编写无符号值有任何不同。也就是说,如果您实际上不知道字节级发生了什么。
- @当我看到一位语言设计师引用这句话的时候,我也做了一次重复。没有比无符号整数更简单的了。有符号整数很复杂。尤其是当你考虑晶体管级的比特旋转时。有符号整数是如何移动的?我不得不得出结论,Java设计者对布尔逻辑有一个严重的问题。
- @pp.:C中无符号类型的一个主要问题是它们表示整数和循环组之间的奇怪交叉,因为uint1-uint2被定义为当添加到uint2时产生uint1的值。如果允许隐式强制转换的语言不能参与运算符重载(例如,someUInt32=someUInt16;是合法的,但if (someInt32==someInt16)在没有类型转换的情况下是不合法的),但包含有意义的运算符重载(例如,将有符号值添加到uint值循环组中的量),则可以解决此问题。
- 对我来说,使用图像byte进行任何图像处理都变得更加困难,因为它不能给出一个直接的140灰度,但-116需要& 0xff才能得到正确的值。
- 在处理字节时,我通常不关心符号,但它们都是按照它应该的方式工作的。不过,我还是希望有一种使用无符号字节文字的方法,即编写byte b = 0x99;的可能性。
- FWW,未签名的API最终在Java 8中得到了它的存在。
- @不使用int来执行布尔逻辑。P
- @马修也许你可以用int?不?
- @德亚基尔,这就是你在内心发生的事情。计算能力下降…
- @pp和matthieu我一点也没有找到你。当使用布尔逻辑或处理字节时,我必须处理位,而不是它的输出整数值。远远地说,比特的行为方式是一样的,并不关心符号。符号和最小-最大字节值对我们人类很重要。所以,如果我需要显示字节值(尽管非常罕见),我只需要为int到byte创建两个端口入端口出函数,反之亦然。
- PeterLawrey:如果Java中没有未签名的字节,EDCOX1 8如何返回未签名字节?因为我们到处都有位,而不是符号,所以我们有两个补码,一个对那些需要"特殊"处理的位的特殊解释;也就是说,你需要知道一些额外的规则,有时你不想这样做。例如,使用InputStream.read()读取的字节来构建32位的值,(b[3] << 24)|(b[2] << 16)|(b[1] << 8)|b[0]…如果您有无符号的字节,这总是有效的。否则,符号扩展会妨碍您,您需要屏蔽。
- @shintakezou the read()返回一个int类型,该类型的范围为无符号字节(0到255),除非到达文件结尾。读取int的一种更有效的方法是以32位值而不是逐字节读取。注意:您必须处理用完的字节,例如,当您实际需要4个字节时,只有2个字节。
- @彼得拉弗里与错误超载的read混淆了:在写之前的评论时,他考虑了read(byte b[], ...)。我目前所做的就是将无符号值保存到一个有符号的更大的"容器"中,除了long的情况。但是,当把C代码转换成Java时,如果有没有签名的类型,你就必须注意自己。
- ShinTakezou个人认为Java除了char之外,应该有无符号类型。esp无符号字节,比有符号字节更自然。
这是从一个采访Gosling和他人的是简单的:
Gosling: For me as a language designer, which I don't really count myself as these days, what"simple" really ended up meaning was could I expect J. Random Developer to hold the spec in his head. That definition says that, for instance, Java isn't -- and in fact a lot of these languages end up with a lot of corner cases, things that nobody really understands. Quiz any C developer about unsigned, and pretty soon you discover that almost no C developers actually understand what goes on with unsigned, what unsigned arithmetic is. Things like that made C complex. The language part of Java is, I think, pretty simple. The libraries you have to look up.
- 我将不得不不同意高斯林这里有一个具体的例子(从CLR不少于)。给数组一个有符号的整型长度值或无符号的长度更令人困惑的是什么?数组不可能有负的长度,但是我们的API表明这是可能的。
- 把Java简单化的理由是把我们弄得一团糟的一部分,因为缺少了模板,它们最终被引入了语言中,因为替代品太麻烦了。我认为我们可以用一个适当的类来支持无符号int,但是它不需要prim
- @uri为true,但它的性能几乎肯定不如JVM中的原始实现。
- 不过,这一问题多久出现一次?我也不确定命令和类型是如何在字节码中编码的,也许添加无符号也会影响指令集?
- @如果你做数学密集型的工作,这可能是一个大问题。考虑基元类型的抖动。基本体上的数学指令可以很容易地JIT到相应的程序集中。但是,如果数学是手工实现的,它不会直接转换为汇编,因此性能会受到影响。
- @Jaredpar:嗯,现代(JIT)编译器非常聪明,可以优化很多。如果猜测在许多情况下,一个简单的无符号类可以优化为对无符号整数执行本机CPU操作。所以我认为它不一定是原始的。事实上,许多人认为原语是(不再)真正必要的。例如,smalltalk没有原语,只有对象。
- 如果Java需要无符号整数,因为数组索引不能是负的,那么它也需要子Branges(la Pascal),因为数组索引不能大于数组大小。
- Uri,我认为泛型(不是模板)应该是Java,只是把规范(和实现)弄对是很困难的。有些人甚至可能认为应该花更多的时间。
- 有一段关于高斯林在上一个雅瓦波利斯讲述故事的记录(在它成为德沃克斯之前)。布洛赫指出,给出的示例也适用于有符号整数。高斯林被这些字眼弄糊涂了。明智的语言应该只使用任意大小的整数。
- 好吧,他只是告诉我们不使用无符号类型的好处。现在让我们来计算一下缺点…
- 比起语言简单,我更喜欢代码简单。这就是我讨厌Java的原因。
- @PIU:更糟糕的是语言的简单化,在这种情况下,某些规则在所有上下文中都适用的要求迫使选择次优规则。我能看到允许隐式浮点到双精度转换(反之亦然)的唯一原因是,当应用于混合浮点和双精度时,允许避免使==作为等价运算符以外的其他运算符工作;我假定,避免==作为非等价运算符工作的更好方法。这种情况将是不允许直接比较float--double,这几乎总是错误的。
- 我想这家伙没有意识到写二进制文件可能会导致很多痛苦,当某人只有128作为一个字节的最高值。
- 对于某些事物来说,Java可能比C++更简单,但也有一些丑陋的东西。许多图书馆的课程有些复杂(例如日期和日历)。考虑一个有趣的事实:A A(A A)是一个有效的方法定义:d
- 作为一个开发者,我想说的是,一种语言永远不会规定一个人的编码方式,它应该提供设施,并将使用权留给开发者。他为长度为负的数组提供了便利,创造了一个非常好的角盒。
- 作为一名开发人员,我觉得高斯林认为我不够聪明,无法理解有符号和无符号整数是一种侮辱。Java只是为初学者准备的吗?
- 低着头,戈斯林。这不是Java工具栏,是Java最深的耻辱。
- @ JaredPar,如果您希望类型实际上约束这样的语义,我认为Java缺少和类型和NeXType是更大的正确性障碍。
- 将Java与允许和理解EDCOX1 1的语言进行比较是不公平的,Java可以得到它们的EDCOX1×2的工作,到目前为止,它只比PHP的EDOCX1,2,IMO稍微好一点,Java已经变得过时了,所有这些过于简单化,C.I只是每天扩展和销毁Java。现在,一种不了解unsigned的语言真是太可惜了,因为它声称的"简单"语言有800多页的lang规范,而c允许无符号和指针都有511页的lang规范。这种"简单"语言比c要复杂得多,但拒绝使用简单的unsigned。
- @felipe:我不介意gosling决定不允许不带符号的类型,这些类型的值不都可以表示为int。我认为他的理由不足以证明缺少无符号8位类型,也不足以证明无符号16位类型的目的是存储数字,因为无符号字节类型与int的交互不会比有符号字节类型与int的交互更差:要么升级到int。
- 当你在爪哇中把EDOCX1的10项推广到EDCOX1(6)时,你会被期望得到否定的结果,所以你需要把这个值修剪到最低的8位,比如EDCOX1,12。对于无符号类型,不会出现符号扩展。
- @bit2shift:提升是在没有符号扩展的情况下执行的,而不是使用符号扩展来执行的,但是像"someUnsignedByte>someSignedByte"这样的表达式不会造成任何问题,因为符号扩展了someSignedByte,但是在没有符号扩展的情况下提升了someUnsignedByte,在所有情况下都会产生算术上正确的结果。这种类型不存在"全尺寸"无符号类型的问题,在这种类型中,只有通过升级到更大的类型才能明智地处理交互。
- @supercat试试byte a = (byte)0xF0; int b = a; System.out.println(b);,然后回来告诉我结果。我给你个提示,我是-16。同样,someUnsignedByte > someSignedByte将在具有无符号类型的语言(如C++)中引起EDCOX1×16的警告。
- @ BIT2SHIFT:Java的"字节"类型被签名。如果存在无符号字节类型,则(该类型的)提升将在没有符号扩展的情况下进行。至于后一种比较,我不希望出现警告,因为这两个值都将被提升为"signed in t"类型,并且比较将以数字预期的方式进行。
- 我是一个C开发人员,在Github中我看到很多C开源项目不使用签名类型。为什么我的车应该有我可能记得某个时候使用过的功能?
- 询问任何开发人员关于浮点数的问题,很快你就会发现许多开发人员实际上并不完全理解浮点数算法的进展……TBH我开始受到Java哲学的困扰
阅读之间的线,我认为是这样的:有逻辑
- 通常,Java的设计者想要的曲目可以简化数据类型
- 为日常用途,他们觉得最需要什么数据类型的通用符号
- 为实现某些算法的无符号算术,有时需要的是小,但程序员是搜索算法的实施是一个"知识工作轮做"无符号算术与符号数据类型
不,我说这是一个合理的决策。可能,我会:
- 制造的无符号字节,或至少有符号/无符号提供一个替代,这可能与不同的名称,这一数据类型(它是制作有好的一致性,但当你需要的有符号字节(?)
- 完成了与"短"(你什么时候负载使用的16位有符号的算术?)
安静,有位无符号值kludging,业务上向32位不啊浴,和最不需要的人或部门无符号64位比较。
- 我同意;特别是关于有无符号字节和短字节。
- 我也希望有无符号字节,但我怀疑整数类型之间完全一致性的优势超过了无符号字节带来的便利。
- "出于日常目的,他们认为最常见的需求是签名数据类型"。在我的C++代码中,我经常发现自己在想:"为什么我在这里使用带符号的整数而不是未签名的整数呢?"!我觉得"有符号"是例外而不是规则(当然,它取决于域,但是正整数被称为自然数是有原因的;-)。
- Java已经足够成熟,当第一个Java被写入时,短裤中的算术仍然是有意义的。
- 是的,它们可能有一些特定的类型,比如在C99中,当您需要它们时(文件和网络代码):uint8、int8、uint16、int16等,然后根据平台设置为int32或int64的额外int类型。
- 在进行图像处理时,如果字节是无符号的(应该是无符号的),则大拇指向上指调用无符号字节,这让我花了数小时调试。
- 你会惊讶于使用short的频率——deflate/gzip/inflat算法是16位的,它们严重依赖于短裤……或者至少short[]〔无可否认,它们是本机的,但该算法的Java IMPL携带了极少数的数据〕。后者(short[]与int[]相比具有显著优势,因为它占用的内存少了两倍,内存少=缓存性能更好,性能更好。
- 尽管在特定的应用程序中,您应该衡量使用短裤是否能提供更好的性能,而不是假设它是真的。有可能操作短裤而不是ints(通常是处理器"喜欢使用的类型")所需的额外的机智技巧实际上会对特定应用程序的性能造成损害。不一定,但你应该测试,而不是假设。
- @ NeilCoffey:Java的INT似乎是一个注定要过时的特性,一旦128位和256位处理器变得通用,因为Java定义INT到处都是精确的32位,而在将来,这个大小将不再是任何处理器的首选整数大小,所以我们都将移植所有的代码使用"长隆长"。我相信Java首先不应该是短的,甚至在那时也没有意义,甚至更少。在未来的证明跨平台语言中,任意大小的算术(bigineger)应该是默认的整数,并且具有运算符支持。
- 谎言——你说的是对的,但是到目前为止,64位处理器仍然给32位宽度某种"特权"状态。如果我们真的转移到128位处理器上,那么看看在这一点上32位是否开始变得更加过时将是很有趣的。
- 128位和256位处理器多年来不会流行。Java(希望)已经很久了。
- @Neilcoffey:Int16是CD的本机格式,因此可用于音频应用程序。
- 我不太同意你的回答!拥有一组较小的可用整数类型,并且使字节无符号都是我全心全意支持的好点。
- @Lieryan在这种情况下,虚拟机将简单地处理这个问题,就像当前32位实现中的byte和short值,或者64位实现中的int值一样。这里最坏的情况是性能损失。
这是一个古老的问题,帕特确实简短地提到了查尔,我只是想我应该把这个问题扩展到其他人,他们会在这条路上看到这个问题。让我们仔细看看Java原语类型:
byte—8位有符号整数
short16位有符号整数
int—32位有符号整数
long64位有符号整数
char16位字符(无符号整数)
虽然char不支持unsigned算法,但它本质上可以看作一个unsigned整数。您必须显式地将算术运算转换回char中,但它提供了一种指定unsigned数字的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| char a = 0;
char b = 6;
a += 1;
a = (char) (a * b );
a = (char) (a + b );
a = (char) (a - 16);
b = (char) (b % 3);
b = (char) (b / a );
//a = -1; // Generates complier error, must be cast to char
System. out. println(a ); // Prints ?
System. out. println((int) a ); // Prints 65532
System. out. println((short) a ); // Prints -4
short c = -4;
System. out. println((int) c ); // Prints -4, notice the difference with char
a *= 2;
a -= 6;
a /= 3;
a %= 7;
a ++;
a --; |
是的,没有对无符号整数的直接支持(很明显,如果有直接支持的话,我不需要将大部分操作重新转换成char)。但是,确实存在一个无符号基元数据类型。我也希望看到一个无符号字节,但我想加倍的内存成本,而使用char是一个可行的选择。
编辑
有了JDK8,long和Integer有了新的API,它们在将long和int值视为无符号值时提供了辅助方法。
- compareUnsigned
- divideUnsigned
- parseUnsignedInt
- parseUnsignedLong
- remainderUnsigned
- toUnsignedLong
- toUnsignedString
此外,guava还提供了许多辅助方法来为at整数类型执行类似的操作,这有助于缩小由于缺少对unsigned整数的本机支持而留下的空白。
- 但是,例如,char太小,无法支持long算法。
- 显然,它只是一个16位的值。:)
- 这可能是Java的缺点。
- 希望它们支持字节的无符号值。使事情更容易。
Java也有无符号类型,或至少一个无符号的字符:短。任何借口,那么它将雏鹅动真的只是他的ignorance为什么没有其他的无符号类型。
所以短短裤类型:多媒体是使用所有的时间。原因是你可以安装2在A单样本的32位无符号整型和vectorize许多操作。同样的事情与8位无符号字节的数据。你可以安装4或8个样本vectorizing A寄存器。
- 是的,我敢肯定戈斯林和你相比,对Java一无所知。
- 从他在公共场合所说的话来判断…
- Java是否允许直接在无符号字节量上执行算术运算,或者值总是得到提升吗?有一个无符号类型用于存储,但总是对一个有符号类型执行算术运算,这个类型足够大,能够很好地适应它的语义,但会导致对与"普通"整数大小相同的无符号类型执行操作的成本更高。
- 使用char除了字符之外,其他任何东西都是不好的样式。
- @当然是Starblue,但绕过语言的限制是一种黑客行为。
有符号和无符号整型。特别是在表达的东西是混合在开始和你可能想得到松散混乱的信息。一个有符号整型restricting Java只有真正将事情放大。我很高兴我不担心有符号/无符号的整体业务,虽然我有时做小姐的8位字节中。
- 至于混合有符号/无符号:您可以有无符号类型,但不允许混合(或需要显式转换)。不过,还不清楚是否有必要。
- 在C++中,你必须喷洒EDOCX1×1左右的混合物来混合它们。这真是一团糟。
- 第8位在那里,它只是试图隐藏自己作为标志。
- 32位或更大的类型只会使事情变得混乱。我看不出为什么Java不应该有EDOCX1,2,因为它在Pascal中签名。
- 当你遇到Java中的图像处理问题时,来看看我,你希望字节是未签名的。然后您就会知道,& 0xFF对每个字节进行整型升级会使代码更加混乱。
skeletoncoder.blogspot.com http:/ / / / / java-tutorials-why-no-unsigned.html 2006年09
这家伙说因为C标准定义无符号和有符号整型操作涉及处理为无符号的。这是因为有符号整数负推出在一个大的无符号整型,造成潜在的错误。
- Java签名的整数也会滚动。我不明白你的意思。
- @foo:有符号整数在产生问题之前必须变大。相比之下,在C语言中,将任何负整数(甚至是-1)与任何无符号数量(甚至是零)进行比较时可能会遇到问题。
- 太糟糕了,Java不能包含未签名的类型,但是有一组有限的转换和混合运算符(有点类似于C中可以将5添加到指针中的方法,但是不能将指针与5进行比较)。当存在隐式强制转换时,在混合类型上使用运算符的想法应该强制使用该强制转换(并使用结果类型作为结果类型),这是在.NET和Java中许多可疑设计决策的核心。
- 不要对你的答案大喊大叫,但是把-1作为"未知"年龄(正如文章所说)是"代码气味"的经典例子之一。例如,如果你想计算"爱丽丝比鲍勃大多少岁?",A=25,B=-1,你会得到一个±26的答案,这是完全错误的。正确处理未知值是某种Option,当Some(25) - None返回None时。
我认为它是一个精细的Java,它是没有多complicate添加符号增益。即使在最简化的整数模型,Java程序员不知道基本数值类型的行为只是读的书misconceptions Java puzzlers看看你会微笑。
AS的实用建议:
所以这个答案是"湖从随机数发生器C移植到Java。
- …和移动。
- 是的,对于右移,您必须在>>和>>>之间分别选择signed和unsigned。向左移动没问题。
- @Starblue实际上不适用于short和byte。例如,(byte)0xff>>>1生成0x7fffffff,而不是0x7f。另一个例子:byte b=(byte)0xff; b>>>=1;将导致b==(byte)0xff。当然,您可以执行b=(byte)(b & 0xff >> 1);,但这会增加一个操作(按位)。
- "即使使用简化的模型,大多数Java程序员也不知道基本的数字类型是如何运行的……"在我身上,有些东西只是憎恨一种针对最低公分母的语言。
- 你答案的开头一行,关于更多的复杂和很少的收获,正是我在6年后的文章Nayuki.io/page/unsigned-int-considered-harmful-for-java中所阐述的。
- @你的文章真不错。只需一句小小的注释,我将对比较运算符使用0x8000000的加法,而不是XOR,因为它解释了为什么它可以工作,它将发生比较的连续区域从-maxint移动到0。按位计算,其效果完全相同。
- @Starblue感谢您的夸奖。顺便说一下,我对你的答案进行了一些编辑,以改进事实和措辞,希望你喜欢。关于0x8000000,为什么使用加法?XOR是一个没有进位的简单操作。另外,我在CompareUnsigned()的其他代码中也同样看到了减法。至于解释,我没有详细解释其他任何运算符,因此为了一致性,我无法解释比较黑客…
我知道这个帖子太老了,但是,对于您的兴趣,在Java 8和以后,您可以使用EDCOX1×2的数据类型来表示一个无符号的32位整数,它的最小值为0,最大值为232。1。使用Integer类将int数据类型用作无符号整数,并将compareUnsigned()和divideUnsigned()等静态方法添加到Integer类中,以支持无符号整数的算术运算。
有了JDK8,它确实对它们有一些支持。
尽管GOOLLN的担忧,我们仍然可以看到Java中的无符号类型的完全支持。
- AKA"所以人们真的使用它,我们错了,不包括它开始"-但我们仍然不太相信Java DEVS知道变量是否签署-所以我们不打算在VM中实现它们,或者作为与其签署的表兄弟等价的类型。
我听到的故事,他们都太靠近原包含的Java版本。橡树是一个Java的前体,和在一些大学usigned规格文件有提到的价值。本论文不让它到Java语言。只要能找到任何人。他们只是不可能得到实现,由于时间约束。
- 这样就好了…除了戈斯林采访的证据外,这意味着无符号整数(除了char)被排除在外,因为设计者认为它们是一个坏主意…考虑到语言的目标。
- 如果手头也有书面证据,最好不要在目击证人的证词中放太多的价值。
我曾经在C++标准委员会上与C++进行了一个课程,它暗示Java做出正确的决定避免使用无符号整数,因为(1)大多数使用无符号整数的程序可以和有符号整数一样好,这在人们如何思考方面更自然,并且(2)使用无符号整数会导致大量EAS。在有符号类型和无符号类型之间转换时,创建但很难调试整数算术溢出和丢失有效位等问题。如果使用有符号整数错误地从0中减去1,它通常会更快地导致程序崩溃,并使查找bug比将其包装到2^32-1更容易,并且编译器、静态分析工具和运行时检查必须假定您知道自己在做什么,因为您选择使用无符号算术。此外,负数(如-1)通常可以表示一些有用的内容,例如字段被忽略/默认/未设置,而如果使用无符号,则必须保留一个特殊值(如2^32-1或类似值)。
很久以前,当内存有限,处理器不能同时在64位上自动运行时,每一位的计数都要多得多,因此,有符号字节和无符号字节或短路实际上更重要,显然是正确的设计决策。现在,在几乎所有常规的编程情况下,只使用带符号的int就足够了,如果程序确实需要使用大于2^31-1的值,那么通常只需要一个long。一旦你进入了使用long的领域,就更难找到一个原因来解释为什么你真的不能通过2^63-1正整数。每当我们使用128位处理器时,问题就更少了。
你的问题是"为什么Java不支持无符号的int"?好的。
我对你的问题的回答是Java想要所有的原始类型:字节、char、短、int和长应该分别被当作字节、字、dword和qword来对待,就像汇编一样,Java操作符除了它的字符之外,所有的原始类型都有签名操作,但是只有char,它们只有16位的无符号。好的。
所以静态方法假设也是32位和64位的无符号操作。好的。
您需要最后一个类,它的静态方法可以为无符号操作调用。好的。
您可以创建这个最后一个类,调用它您想要的任何名称,并实现它的静态方法。好的。
如果您不知道如何实现静态方法,那么这个链接可能会对您有所帮助。好的。
在我看来,Java根本不类似于C++,如果它既不支持无符号类型,也不支持运算符重载,那么我认为Java应该被视为完全不同于C++和C.的语言。好的。
顺便说一下,它在语言名称上也完全不同。好的。
所以我不建议在Java中键入类似于C的代码,我不建议在任何情况下键入与C++类似的代码,因为在Java中,您将无法在C++中完成下一步要做的事情,即代码不会继续像C++一样,对我来说,这样的代码是不好的,要改变中间的样式。好的。
我建议对有符号的操作也编写和使用静态方法,因此在代码中不会看到有符号和无符号操作的运算符和静态方法的混合,除非代码中只需要有符号的操作,并且只使用运算符也可以。好的。
另外,我建议避免使用short、int和long原语类型,并分别使用word、dword和qword,您将要为无符号操作和/或有符号操作调用静态方法,而不是使用运算符。好的。
如果您将只执行带符号的操作,并且只在代码中使用运算符,那么可以使用这些基元类型short、int和long。好的。
实际上,语言中不存在word、dword和qword,但是您可以为每个类创建新类,并且每个类的实现应该非常容易:好的。
类字只保留基元类型short,类dword只保留基元类型int,类qword只保留基元类型long。现在,所有无符号和有符号的方法都是静态的或不是您所选择的,您可以在每个类中实现,即所有16位操作都是无符号的和有符号的,在word类上给出含义名称;所有32位操作都是无符号的和有符号的,在dword类上给出含义名称;所有64位操作都是无符号的和有符号的。d在Qword类上给出意义名称。好的。
如果你不喜欢给每种方法提供太多不同的名字,你可以在爪哇中使用重载,很好地读取Java也没有删除它!好的。
如果您想要方法而不是8位有符号操作的运算符,以及8位无符号操作的方法(根本没有运算符),那么您可以创建字节类(注意,第一个字母"b"是大写的,因此这不是基元类型byte),并实现此类中的方法。好的。
关于传递值和传递引用:好的。
如果我没有错,就像在C中一样,原语对象是按值自然传递的,而类对象是按引用自然传递的,这意味着类型为byte、word、dword和qword的对象将按引用传递,而不是按默认值传递。我希望Java的结构对象是C语言,因此,所有字节、单词、dword和qword都可以实现为结构,而不是类,因此默认情况下它们是通过值传递的,而不是默认引用的,就像C语言中的任何结构对象一样,原始类型通过值传递,而不是默认引用,但是因为Java比C语言更坏,我们必须处理它,然后在那里进行处理。仅为类和接口,默认情况下通过引用传递,而不是通过值传递。因此,如果您想通过值而不是引用来传递字节、word、dword和qWord对象,就像Java中的任何其他类对象一样,也在C语言中,则必须简单地使用复制构造函数,就是这样。好的。
这是我唯一能想到的解决办法。我只希望我可以将原始类型Type填充到Word、Dword和QWord中,但是Java既不支持Type,也不支持使用,不像支持使用的C,它相当于C的TyPulf。好的。
关于输出:好的。
对于相同的位序列,您可以用多种方式打印它们:二进制、十进制(如c printf中的%u含义)、八进制(如c printf中的%o含义)、十六进制(如c printf中的%x含义)和整数(如c printf中的%d含义)。好的。
注意,c printf不知道作为参数传递给函数的变量的类型,因此printf只知道从char*对象传递给函数的第一个参数的每个变量的类型。好的。
因此,在每个类中:byte、word、dword和qword,您可以实现print方法并获得printf的功能,即使类的基元类型是有符号的,您仍然可以通过执行一些涉及逻辑和移位操作的算法将其打印为无符号的,以便将数字打印到输出。好的。
不幸的是,我给你的链接没有显示如何实现这些打印方法,但我相信你可以谷歌的算法,你需要实现这些打印方法。好的。
我只能回答你的问题并建议你。好的。好啊。
- MASM(Microsoft汇编程序)和Windows将字节、字、双字、Qword定义为无符号类型。对于masm,sbyte、sword、sdword、sqword是有符号的类型。
因为以东1〔0〕型是纯粹的邪恶。
事实上,在c-unsigned - int中,产生unsigned更为邪恶。
下面是一个问题的快照,这个问题让我不止一次感到痛苦:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| // We have odd positive number of rays,
// consecutive ones at angle delta from each other.
assert( rays.size() > 0 && rays.size() % 2 == 1 );
// Get a set of ray at delta angle between them.
for( size_t n = 0; n < rays.size(); ++n )
{
// Compute the angle between nth ray and the middle one.
// The index of the middle one is (rays.size() - 1) / 2,
// the rays are evenly spaced at angle delta, therefore
// the magnitude of the angle between nth ray and the
// middle one is:
double angle = delta * fabs( n - (rays.size() - 1) / 2 );
// Do something else ...
} |
你注意到那个虫子了吗?我承认,我只是在和调试器一起使用之后才看到它。
由于n是无符号类型size_t,所以整个表达式n - (rays.size() - 1) / 2的计算结果为unsigned。该表达式是n射线中间的一个有符号位置:左边中间的第一条射线的位置为-1,右边的第一条射线的位置为+1等,取abs值乘以delta角,得到n射线和Th之间的角度。中间的一个。
不幸的是,对于我来说,上面的表达式包含了邪恶的无符号表达式,它的计算结果不是-1,而是2^32-1。随后转换为double的版本密封了这个错误。
在错误地使用unsigned算术导致一两个错误之后,人们必须开始怀疑自己得到的额外位是否值得额外的麻烦。我尽量避免在算术中使用unsigned类型,尽管它仍然用于二进制屏蔽等非算术运算。
- 向Java添加"未签名的long"会很尴尬。但是,添加较小的无符号类型应该没有问题。特别是小于"int"的类型可以通过以数字明显的方式升级为"int"来轻松处理,"unsigned int"可以通过说涉及有符号int和无符号int的操作将两个操作数升级为"long"来处理。唯一的问题是涉及无符号长和有符号数量的操作,因为没有能够表示两个操作数的所有值的类型。
- @supercat:如果每次操作都将unsigned转换为int,那么unsigned的用途是什么?它将没有任何可与short区分的功能。如果只在混合操作(如unsigned+int或unsigned+float上转换为int,那么仍然存在((unsigned)25-(unsigned)30)*1.0 > 0问题,这是unsigned相关错误的主要原因。
- 许多对无符号类型的操作将提升为"long"。在将结果存储回无符号类型时,要求显式强制转换将导致与short和byte相同的麻烦,但如果类型主要是存储格式而不是计算格式,则这不应该是问题。在任何情况下,短于"int"的无符号类型应该能够轻松地升级到"int"。
- 我不喜欢这个答案,因为它使用的参数"无符号整数是邪恶的,不应该存在,因为它们永远不能被签名"。任何试图从无符号整数中减去的人都应该已经知道这一点。至于可读性,C并不以易于理解而著称。此外,"多余的比特不值得额外的麻烦"这个(半)论点也很弱。错误处理而不是exit(1);真的"值得额外的麻烦"吗?不能够打开大文件真的值得安全,经验不足的Java程序员不会弄乱使用EDCOX1 0?
- 我理解为什么Java选择排除无符号整数,但我不认为这是因为这些原因之一。为了提高可读性,也许,为了使JVM更容易实现,当然,我不认为他们仅仅因为它们永远是未签名的而选择排除它们(在这种情况下,它们可以选择由于某些原因对未签名的签名进行减法),或者因为额外的位不值得(最肯定的是,我发现了多个Java)。试图处理大文件时程序崩溃)。
- 此外,即使程序没有崩溃,它们也会严重限制灵活性,例如,Minecraft命令块字符限制。
- 我在这段代码中看到的唯一邪恶的东西是n - (rays.size() - 1) / 2。您应该始终使用二进制运算符,因为代码的读卡器不需要假定任何有关计算机程序中操作顺序的内容。仅仅因为我们通常说a+bc=a+(bc)并不意味着在读取代码时可以假定这一点。此外,应在循环外部定义计算,以便在不存在循环的情况下对其进行测试。这是一个错误,不能确保类型排列整齐,而不是无符号整数的问题。在C语言中,由你来确定你的类型是否一致。
- 在C程序中,对两种不同类型的事物执行二进制操作是愚蠢的缩影。这与使用int a=2;int*b=&;a;int c=a+b然后抱怨a+b不给您4没有什么不同:这取决于您确保类型对齐;不要依赖编译器以您希望的方式强制您的类型。
- 我重复一遍;这不是编译器的坏处;这是您的代码令人厌恶的误导。角度是双精度的,delta是上帝知道什么类型,n是无符号int,ray.size()是上帝知道什么类型,1是int,2是int。fabs接受双精度并返回双精度。(+)接受a=>(a,a)并返回a,(/)接受a=>(a,a)并返回a。当然,您有两个构造,我们甚至不知道它们是什么类型,除此之外,您可以混合无符号和有符号,而不承认二元运算符是多态的。
- 在"数学"表达的世界里,我一直都看到这个,这让我很厌恶。如果你不理解基本的lambda演算/haskell/类型必须排列的思想,你就不应该写任何包含转换链的生产代码;即使无符号的行为正确,写这段代码的心理状态也会在不久后引起其他错误。您必须始终了解您正在操作的类型的世界,并且更愿意将它们放入单个类型的单个世界(在本例中,是一个双精度的世界)。
- @dmitry:这个代码段很简单。你为什么不在这里写你认为"正确的方式"。
- @它甚至不能被重写,代码示例中有一些我们不知道实现的信息。我们不知道什么是射线,它的尺寸是多少。我们不知道delta是什么类型。试图重写包含您不知道的依赖项的内容是不诚实的。
- @Dmitry,我的观点是,严格遵循代码"应该"的理论规则,使得它在现实生活中效率低下。如果您尝试实现类似于该函数或OOP样式的东西,那么您将隐式地添加一些不必要的指令。我已经看到了看起来无害的OOP代码的2倍内存和运行时惩罚,这当然是商业代码的巨大市场劣势。
- @德米特里:这是其中一个:class Point { float x, y; public: virtual ~Point() {} };你能指出为什么这个类的商业软件使用的内存比完全相同功能的竞争对手多2倍吗?这是正确的:使Point::~Point()虚拟化使它对OOP友好(在这种情况下这是不必要的),但这也为8字节结构增加了8个额外字节(这对内存占用至关重要)。
- @迈克尔,我不知道你在说什么。我不是在讨论结构;我是在讨论一个事实,即您在一个公式中使用了不同的非显式类型,并且期望得到正确的结果。如果添加三个完全不同类型的变量,如果结果没有意义,您不会感到惊讶,必须首先将它们放在同一个类型空间中(例如双精度)。不要对三个不同类型的变量执行二进制(A->A->A)操作,首先要使它们的类型相同。即使语言有协同作用,你也希望控制这个协同作用。
- @迈克尔,我也不知道你说的让析构函数变得更面向OOP是什么意思。OOP不是关于子类化,而是通过在源代码依赖项之间战略性地放置接口来控制依赖项的方向,使源代码依赖项成为系统中的插件,而不是耦合到系统中。如果您希望类被子类化,并且Point不需要被任何健全的系统子类化,那么您只需要虚拟析构函数,如果您愿意,您可以委托它。
我想一个不幸的附带效应。在Java的嵌入式数据库系统,数你可以有一个32位的ID字段是2^31 -1(2~32,价值20亿的困境,困境~40)。
- 负ID不起作用有什么原因吗?
- 他可能在考虑数组,不能使用负整数作为索引。可能。
- 当数据库中的自动增量字段溢出时,它们通常会出错。
我之所以这么做是因为他们太懒了,无法实施/纠正这个错误。建议C/C++程序员不理解无符号、结构、联合、位标志…只是荒谬而已。
你正在和一个BASH/BASH/Java程序员交谈,开始编程一个LAC,没有任何真正的知识,或者你只是在说自己的想法。;)
当你每天处理文件或硬件的格式时,你开始怀疑他们到底在想什么。
这里的一个好例子是尝试使用无符号字节作为自旋转循环。对于那些不理解最后一句话的人来说,你究竟是如何称自己为程序员的。
直流
- 只为了好玩,谷歌的短语"自我旋转循环"。显然,丹尼斯·科是世界上唯一值得自称为程序员的人。
- 这个答案太糟糕了,很有趣