睡眠的意义(0)

我曾经在我的代码的某些部分看到Sleep(0) ,其中有些无限/长时间循环可用。 我被告知,这将使时间片可用于其他等待进程。 这是真的? Sleep(0)有意义吗?

根据MSDN的睡眠文档:

值为零将导致线程放弃其时间片的其余部分到准备运行的任何其他线程。 如果没有其他线程准备运行,则该函数立即返回,线程继续执行。

重要的是要知道的是,这样可以让其他线程有机会运行,但是如果没有准备好运行的话,那么线程将继续运行 – 因为某些东西总是在运行,所以CPU使用率保持在100%。 如果while循环在等待某个条件时只是在旋转,则可能需要考虑使用像事件一样的同步原语来hibernate,直到满足条件,或者hibernate一段时间以防止最大化CPU。

是的,它使其他线程有机会运行。

值为零将导致线程放弃其时间片的其余部分到准备运行的任何其他线程。 如果没有其他线程准备运行,则该函数立即返回,线程继续执行。

资源

恐怕我不能在这里改进MSDN文档

值为零将导致线程放弃其时间片的其余部分到准备运行的任何其他线程。 如果没有其他线程准备运行,则该函数立即返回,线程继续执行。

Windows XP / 2000:值为零会导致线程将其时间片的其余部分放弃到准备运行的同等优先级的任何其他线程。 如果没有其他相同优先级的线程准备运行,则该函数立即返回,线程继续执行。 此行为从Windows Server 2003开始更改。

请同时注意(通过upvote)这里关于效率问题的两个有用答案。

要小心睡眠(0),如果一个循环迭代执行时间短,这可以显着减慢这种循环。 如果这对于使用它很重要,则可以每100次迭代一次调用Sleep(0)。

Sleep(0); 在该指令中,系统调度器将检查任何其他可运行线程,并可能根据线程优先级给他们一个使用系统资源的机会。

在Linux上有一个特定的命令: sched_yield()从手册页:

sched_yield()会导致调用线程放弃CPU。 线程被移动到队列的末尾以获得其静态优先级,并且新的线程开始运行。

如果调用线程是当时最高优先级列表中唯一的线程,那么在调用sched_yield()之后它将继续运行。

sched_yield()策略性调用可以通过让其他线程或进程有机会在调用者释放(大量)争用的资源(例如互斥锁)时提高性能。 避免不必要地或不恰当地调用sched_yield() (例如,当其他可调度线程需要的资源仍然由调用者保持时),因为这样做会导致不必要的上下文切换,这会降低系统性能。

睡眠(0)是一个强大的工具,它可以提高某些情况下的性能。 在特殊情况下可能会考虑在快速循环中使用它。 当一组线程响应最大时,它们都应该经常使用Sleep(0)。 但是在代码的上下文中寻找一个响应手段的统治者是至关重要的。

我已经在https://stackoverflow.com/a/11456112/1504523中提供了一些细节;

在一个应用程序中……主线程寻找要做的事情,然后通过一个新的线程启动“工作”。 在这种情况下,你应该在主线程中调用sched_yield()(或者sleep(0)),这样就不会让工作“寻找”,而更重要的是“工作”。 我更喜欢睡觉(0),但有时这是过度的(因为你睡了一小会儿)。

我正在使用pthreads和出于某种原因在我的Mac编译器没有findpthread_yield()声明。 但似乎睡眠(0)是一回事。

错误消息:(提供程序:共享内存提供程序,错误:0 – 没有进程在pipe道的另一端。

我想在Windows Server 2003上部署我的网站。我是否错过了什么是错误消息,如何纠正? 谢谢

我有错误消息:

与服务器build立了连接,但在login过程中发生错误。 (提供程序:Shared Memory Provider,错误:0 – pipe道的另一端没有进程。)说明:在执行当前Web请求期间发生未处理的exception。 请查看堆栈跟踪,了解有关错误的更多信息以及源代码的位置。

exception详细信息:System.Data.SqlClient.SqlException:与服务器build立了连接,但在login过程中发生错误。 (提供程序:共享内存提供程序,错误:0 – 没有进程在pipe道的另一端。

源错误:

在执行当前Web请求期间生成未处理的exception。 有关exception的来源和位置的信息可以使用下面的exception堆栈跟踪来标识。

堆栈跟踪:

[SqlException(0x80131904):与服务器build立了连接,但在login过程中发生错误。 (提供程序:共享内存提供程序,错误:0 – 没有进程在pipe道的另一端。)]
System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection拥有对象)+1019
System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection拥有连接)+108
System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection,DbConnectionFactory connectionFactory)+126
System.Data.SqlClient.SqlConnection.Open()+125
NHibernate.Connection.DriverConnectionProvider.GetConnection()+104
NHibernate.Tool.hbm2ddl.SuppliedConnectionProviderConnectionHelper.Prepare()+15 NHibernate.Tool.hbm2ddl.SchemaMetadataUpdater.GetReservedWords(方言方言,IConnectionHelper connectionHelper)+89
NHibernate.Tool.hbm2ddl.SchemaMetadataUpdater.Update(ISessionFactory sessionFactory)+80
NHibernate.Impl.SessionFactoryImpl..ctor(configurationcfg,IMapping映射,设置设置,EventListeners监听器)+599
NHibernate.Cfg.Configuration.BuildSessionFactory()+104
C:\ Dev \ Code \ API \ Data \ SessionManager.cs中的MyProject.API.Data.SessionManager..cctor()

通常,要解决此问题,请转到SQL Serverconfigurationpipe理器(SSCM)并:

  1. 确保共享内存协议已启用
  2. 确保命名pipe道协议已启用
  3. 确保TCP / IP已启用,并在设置中的命名pipe道之前

也许它可以帮助: 无法打开到SQL Server的连接

我有这个相同的错误信息,原来是因为我没有启用混合模式validation。 我只在Windows身份validation。 这在vSphere的默认MSSQL部署中很常见,在升级到vSphere 5.1时会成为问题。

要更改为混合模式身份validation,您可以按照http://support.webecs.com/kb/a374/how-do-i-configure-sql-server-express-to-enable-mixed-mode-authentication中的说明进行操作。; aspx 。

我在SQL Server Management Studio中遇到了同样的错误。

我发现要查看更具体的错误,请查看由SQL Server创build的日志文件。 当我打开日志文件时,我发现这个错误

无法连接,因为已达到“2”用户连接的最大数量。 系统pipe理员可以使用sp_configure来增加最大值。 连接已closures

我花了相当长的一段时间搞清楚这一点。 最后运行下面的代码修复了我的问题。

sp_configure 'show advanced options', 1; go reconfigure go sp_configure 'user connections', 0 go reconfigure go 

更多关于这里和这里

只是另一种可能。 我不得不重新启动sql服务器来解决这个问题。

您应该启用服务器身份validation模式为混合模式,如下所示:在SQL Studio中,select您的服务器 – >属性 – >安全 – >selectSqlServer和窗口身份validation模式。

我今天得到这个错误。 在我的情况下,查看SQL服务器上的ERRORLOG文件给了我这个错误:

用户login失败。 原因:无法打开login属性中指定的数据库。

这是因为我前几天删除了这个用户的“默认数据库”。 将默认数据库设置为我的新数据库修复了问题。

希望这可以帮助别人。

转到SQL Server使用Windows凭据 – >login – >selectlogin – >在属性 – >检查login是否启用/禁用。 如果禁用,使其启用,这个解决scheme为我工作。

安装MSSQL服务器时启用混合身份validation模式。 还为sa用户提供密码。

这是旧的,但我有连接对话框的问题,它仍然是我已经删除的数据库默认。 通过运行这些命令,提示符中的默认数据库不会改变。 我读了一些我现在找不到的地方,如果打开“连接到服务器”对话框,然后select“选项”,并通过input默认数据库(从下拉菜单中select“ ”)select“连接属性”数据库将保持在input的新值上。 这听起来像是一个缺陷,但如果有人想知道这个问题,那么应该解决这个问题,至less在SQL Server 2012

我忘了添加“密码= xxx;” 在我的情况下连接string。

如何将缺失的数据设为高分辨率默认值为0

我有一个1分钟的时间间隔。 我想在缺失点为0的图表中显示。

我find了xAxis.ordinal,并将其closures,显示正确的间隔时间序列。 问题在于它直接在点之间划线,而不会为0丢失数据。

一种方法是预处理数据,用0代替null

 var withNulls = [null, 12, 23, 45, 3.44, null, 0]; var noNulls = withNulls.map(function (item) { return (item === null) ? 0 : item; }); 

保存在jsfiddle上的示例: http : //jsfiddle.net/7mhMP/

我已经search了HighCharts的API参考 ,但是他们不提供这个选项。 他们所提供的是当null数据介于两者之间(仅限线和面积图)时禁用点的连接的选项:

 var chart = new Highcharts.Chart({ plotOptions: { line: { connectNulls: false } } }); 

这是根据API的默认设置,所以我不知道为什么你的数据连接之间的null值。 也许他们最近改变了默认值?

缺少数据的HighChart示例

我觉得这是你的数据的一个很好的表示,因为默认null似乎是误导。

你必须填补错过的数据为0.因为高图不知道xAxis区间。

如果你有一个1 分钟的时间间隔,你应该把每一个缺less的分钟数据设置为0; 如果您每隔一天有一个时间序列,则应将每个缺失的date数据设置为0。

我有同样的问题,我的理解是,你应该在数据库中设置你的数据结构为VARCHAR,并将默认值设置为null,所以你没有数据的地方变成NULL。 然后它接受空值和高图不显示和连接缺less的区域与null值。
此外,您必须接收数据为NULL ,不要将其更改为''
看到这个工作的例子:

 var chart = new Highcharts.Chart({ chart: { defaultSeriesType: 'spline', // use line or spline renderTo: 'container1' }, xAxis: { categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] }, series: [{ data: [9, 4,null, 2, 1, 0, 6, 5, 4, 1, 6, 4] }] }); 

这里是两个不同的图表使用null''

更新:
如果你正在使用parseINT来推送数据,你应该记住, parseINT(NULL)会给你NAN所以对于这个bug,尝试用下面的方法手动推NULL:

 var val = parseInt(rows[i]); if (isNaN(val)) { val = null; result.push(val); } 

如果我将数组初始化为0,会发生什么?

比方说,我有一个像这样的function:

void myFunc(List<AClass> theList) { string[] stuff = new string[theList.Count]; } 

我通过一个空的名单。

将东西是一个空指针? 或者它会成为一个指向未初始化的内存中的随机地点的指针?

它将创build一个空的数组对象。 这仍然是一个非常有效的对象,并且在内存中占用了非零的空间。 它仍然会知道它自己的types,数量 – 它不会有任何元素。

空数组通常用作不可变的空集合是有用的:您可以无限次地重用它们; 数组本身是可变的,但只是在他们的元素方面 ……在这里,我们没有任何元素可以改变! 由于数组不可resize,空数组是完全不可变的。

请注意,有一个空数组而不是空引用通常是有用的:返回集合的方法或属性应该总是返回一个空集合而不是空引用,因为它提供了一致性和一致性 – 而不是让每个调用者检查无效性。 如果你想避免分配多次,你可以使用:

 public static class Arrays<T> { private static readonly T[] empty = new T[0]; public static readonly T[] Empty { get { return empty; } } } 

那么你可以使用:

 return Arrays<string>.Empty; 

(或其他),当你需要使用一个特定types的空数组的引用。

为什么要这样? 它将指向一个大小为0的数组,这是完全有效的。

我认为这里的混淆是由于大小0的数组表示缺less数据或variables设置为空的歧义(对于空string或string引用设置为空的string存在相同的歧义)。 两者都是表明这种缺席的有效方式,只有一种才是更合理的。 因此,在一些数据库(特别是Oracle)上,一个空string等于NULL值,反之亦然,一些编程语言(我认为,C#的新版本就是其中之一)允许指定引用永远不为null,也消除了模糊性。

这是很好的代码。 你会得到一个零对象(分配)的数组对象。

stuff将是一个长度为theList.Count的数组的引用,所有条目初始化为default(string) ,这是null

以下是C#语言规范:

  • 尺寸长度的计算值经过validation如下。 如果一个或多个值小于零,则引发System.OverflowException,并且不会执行进一步的步骤。
  • 具有给定维度长度的数组实例被分配。 如果没有足够的可用内存分配新实例,则抛出System.OutOfMemoryException,并且不会执行进一步的步骤。

因此,对于零长度,分配内存。

如果theList是一个实际的List对象,并且只是空的,那么theList.Count将返回0.这意味着声明变成

 string[] stuff = new string[0]; 

换句话说, stuff只是一个长度为0的数组(string)。

只要你确保你实际传入方法的List <>被初始化了,就像

 List<Stuff> myStuff = new List<Stuff>; 

该列表不会指向null。 这将是一个零东西的清单。

'更新无效:部分0中的行数无效

我已阅读所有关于这个相关的post,我仍然有一个错误:

'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (5) must be equal to the number of rows contained in that section before the update (5), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).' 

以下是详细信息:

.h我有一个NSMutableArray

 @property (strong,nonatomic) NSMutableArray *currentCart; 

.m我的numberOfRowsInSection看起来像这样:

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. return ([currentCart count]); } 

要启用删除并从arrays中删除对象:

 // Editing of rows is enabled - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { //when delete is tapped [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; [currentCart removeObjectAtIndex:indexPath.row]; } } 

我认为通过让我的数量依赖于数组的数量我正在编辑将确保正确的行数? 无论如何,当你删除一行时,无需重新加载表就可以做到这一点?

调用deleteRowsAtIndexPaths:withRowAnimation: 之前,需要从数据数组中删除对象。 所以,你的代码应该是这样的:

 // Editing of rows is enabled - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { //when delete is tapped [currentCart removeObjectAtIndex:indexPath.row]; [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; } } 

您还可以使用数组创build快捷方式@[]来简化代码:

 [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; 

“无效0”和“未定义”之间的区别

我正在使用“Closure编译器” ,编译我的脚本时,我花了以下几点:

编译之前:

// ==ClosureCompiler== // @compilation_level SIMPLE_OPTIMIZATIONS // @output_file_name default.js // @formatting pretty_print,print_input_delimiter // ==/ClosureCompiler== var myObj1 = (function() { var undefined; //<----- declare undefined this.test = function(value, arg1) { var exp = 0; arg1 = arg1 == undefined ? true : arg1; //<----- use declare undefined exp = (arg1) ? value * 5 : value * 10; return exp; }; return this; }).call({}); var myObj2 = (function() { this.test = function(value, arg1) { var exp = 0; arg1 = arg1 == undefined ? true : arg1; //<----- without declare undefined exp = (arg1) ? value * 5 : value * 10; return exp; }; return this; }).call({}); 

编译:

 // Input 0 var myObj1 = function() { this.test = function(b, a) { a = a == void 0 ? true : a; //<----- var c = 0; return c = a ? b * 5 : b * 10 }; return this }.call({}), myObj2 = function() { this.test = function(b, a) { a = a == undefined ? true : a; //<----- var c = 0; return c = a ? b * 5 : b * 10 }; return this }.call({}); 

有了这个我相信使用“void 0”和“undefined”的问题,在使用上还是有区别的呢,还是两种情况都好呢?

编辑

如果我定义用“void 0”编译的“var undefined”,如果我没有定义“undefined”编译为“undedined”,那么不是“undefined”和“void 0”

testing

编辑二:性能,基于这个链接

代码和testing

IE 8:
types:228ms
undefined:62ms
无效0:57ms

Firefox 3.6:
types:10ms
undefined:3ms
无效0:3ms

歌剧11:
types:67ms
undefined:19ms
无效0:20ms

Chrome 8:
typeof:3ms
undefined:5ms
无效0:3ms

来自MDN :

void运算符评估给定的expression ,然后返回undefined

该运算符允许将产生副作用的expression式插入到期望未定义expression式的地方。

void运算符通常仅用于获取undefined原始值,通常使用“ void(0) ”(相当于“ void 0 ”)。 在这些情况下,可以使用全局variablesundefined (假设它尚未分配给非默认值)。

Closure Compiler在void 0交换,因为它包含的字符less于undefined的字符, 因此会生成等效的较小的代码


回复:OP评论

是的,我读了文档,但在我给例子,“谷歌closures”的情况下使用“无效0”和另一个“未定义”

我相信这实际上是Google Closure Compiler中的一个错误 !

void exprundefined之间唯一真正的语义差别是,在ECMAScript 3中 ,全局对象(浏览器环境中的window.undefined )的undefined属性是可写的,而void运算符将始终返回undefined值。

一个常用的模式,使用undefined而不用担心,只是声明一个参数,而不是传递任何东西:

 (function (undefined) { //... if (foo !== undefined) { // ... } })(); 

这将允许缩小器将参数缩小为单个字母(甚至比void 0 :)更短,例如:

 (function (a) { //... if (foo !== a) { // ... } })(); 

只是之前的所有答案的后续行动。

它们看起来是一样的,但是对于编译器来说,它们是完全不同的。

这两个代码段编译为不同的输出,因为一个引用了一个局部variables(var未定义),编译器只是简单地将其内联,因为它只用了一次,不超过一行。 如果多次使用,则不会发生这种内联。 内联提供了“未定义”的结果,其短于表示为“空0”。

没有局部variables的variables引用的是全局对象下的“未定义”variables,这个variables被Closure编译器自动“外部化”(实际上是所有的全局对象属性)。 因此,不会发生重命名,也不会发生内联。 瞧! 仍然是“未定义的”。

没有什么区别,自己动手:

 void 0 === undefined 

将评估为true
undefined3个字符长,我想这就是为什么他们这样使用它。

初始化一个结构为0

如果我有这样的结构:

typedef struct { unsigned char c1; unsigned char c2; } myStruct; 

什么是最简单的方法来初始化这个结构为0? 以下就足够了吗?

 myStruct _m1 = {0}; 

或者我需要显式初始化每个成员为0?

 myStruct _m2 = {0,0}; 

第一个是最简单的( 涉及较less的input ),并且保证工作,所有成员将被设置为0 [参考文献1]
第二个更可读。

select取决于用户的偏好或你的编码标准的要求。

[参考1] 参考C99标准6.7.8.21:

如果大括号包含的列表中的初始值设定项less于聚合的元素或成员,或者用于初始化比数组中的元素大小的数组的stringstring中的较less字符,则聚合的其余部分应被隐式地初始化为具有静态存储持续时间的对象。

好阅读:
C和C ++:自动结构的部分初始化

如果数据是一个静态或全局variables,默认情况下它是零填充的,所以只需声明它myStruct _m;

如果数据是本地variables或堆分配区域,请使用memset清除它:

 memset(&m, 0, sizeof(myStruct)); 

目前的编译器(例如最近版本的gcc )在实践中优化了这一点。 这只有当所有的零值(包括空指针和浮点零)都表示为全零位时才有效,在所有我知道的平台上都是如此(但是C标准允许实现,这是错误的;我不知道这样的实现) 。

你也许可以编写myStruct m = {}; (这可能被接受为延伸),但我觉得很难看。 如果结构的第一个成员是非标量,即联合,结构或数组,则编码myStruct m = {0}; 是不正确的。

我的感觉是,使用本地结构的memset是最好的,它传达了更好的事实,在运行时,必须做的事情(通常,全局和静态数据可以被理解为在编译时初始化,没有任何代价在运行)。

请参阅第6.7.9节初始化:

21如果大括号括起来的列表中的初始值设定项less于聚合的元素或成员,或者用于初始化比数组中元素大的已知大小数组的string文字中的较less字符,则聚合的其余部分应该被隐式地初始化为具有静态存储持续时间的对象。

所以,是的,他们都工作。 请注意,在C99中,也可以使用一种称为指定初始化的新的初始化方法:

 myStruct _m1 = {.c2 = 0, .c1 = 1}; 

如何捕捉整数(0)?

比方说,我们有一个产生integer(0)的语句,例如

  a <- which(1:3 == 5) 

捕捉这个最安全的方法是什么?

这是R的打印一个零长度vector(一个整数)的方式,所以你可以testinga长度为0的:

 R> length(a) [1] 0 

可能值得重新思考你正在使用的策略来确定你想要的元素,但没有进一步的具体细节,很难build议一个替代策略。

如果它是特定的零长度整数 ,那么你想要的东西

 is.integer0 <- function(x) { is.integer(x) && length(x) == 0L } 

检查:

 is.integer0(integer(0)) #TRUE is.integer0(0L) #FALSE is.integer0(numeric(0)) #FALSE 

也许是脱离主题,但R具有两个很好,快速和空知道的function,用于减less逻辑向量 – anyall

 if(any(x=='dolphin')) stop("Told you, no mammals!") 
 if ( length(a <- which(1:3 == 5) ) ) print(a) else print("nothing returned for 'a'") #[1] "nothing returned for 'a'" 

再次想到,我认为任何比length(.)更美丽:

  if ( any(a <- which(1:3 == 5) ) ) print(a) else print("nothing returned for 'a'") if ( any(a <- 1:3 == 5 ) ) print(a) else print("nothing returned for 'a'") 

受Andrie的回答的启发,你可以使用identical ,避免任何属性问题,通过使用这个对象类的空集,并将它与该类的一个元素相结合:

 attr(a,"foo")<-"bar" > identical(1L,c(a,1L)) [1] TRUE 

或者更一般地说:

 is.empty <- function(x, mode=NULL){ if (is.null(mode)) mode <- class(x) identical(vector(mode,1),c(x,vector(class(x),1))) } b <- numeric(0) > is.empty(a) [1] TRUE > is.empty(a,"numeric") [1] FALSE > is.empty(b) [1] TRUE > is.empty(b,"integer") [1] FALSE 

为什么我=我+我给我0?

我有一个简单的程序:

public class Mathz { static int i = 1; public static void main(String[] args) { while (true){ i = i + i; System.out.println(i); } } } 

当我运行这个程序时,我所看到的全部为0 。 我会第一次预期我会有i = 1 + 1 ,其次是i = 2 + 2 ,其次是i = 4 + 4等。

这是因为我们试图重新宣布i在左侧,它的值重置为0

如果任何人都可以指出我这个更好的细节。

int更改为int ,并且按照预期似乎正在打印数字。 我很惊讶它的速度达到最大的32位值!

这个问题是由于整数溢出。

在32位二进制补码algorithm中:

i确实开始具有两个幂的值,但是一旦你达到2 30 ,溢出行为就开始了:

2 30 + 2 30 = -2 31

-2 31 + -2 31 = 0

…在int算术。

介绍

问题是整数溢出。 如果溢出,则返回最小值并从那里继续。 如果下溢,则回到最大值并从那里继续。 下面的图片是里程表。 我用这个来解释溢出。 这是一个机械溢出,但仍然是一个很好的例子。

在里程表中, max digit = 9 ,所以超出最大值意味着9 + 1 ,它将带出一个0 ; 但是没有更高的数字变成1 ,所以计数器重置zero 。 你现在想到了 – “整数溢出”的想法。

在这里输入图像说明在这里输入图像说明

inttypes的最大十进制文字是2147483647(2 31 -1)。 从0到2147483647的所有十进制文字可能出现在可能出现的整型文字的任何位置,但文字2147483648可能只出现在一元否定运算符 – 的操作数中。

如果整数加法溢出,那么结果是math和的低位,如用一些足够大的二进制补码格式表示的那样。 如果发生溢出,则结果的符号与两个操作数值的math和的符号不同。

因此, 2147483647 + 1溢出并回绕到-2147483648 。 因此int i=2147483647 + 1会被溢出,这不等于2147483648 。 另外,你说“它总是打印0”。 它不,因为http://ideone.com/WHrQIW 。 下面,这8个数字显示了它的枢轴点和溢出点。 然后开始打印0。 另外,不要惊讶它的计算速度,今天的机器是快速的。

 268435456 536870912 1073741824 -2147483648 0 0 0 0 

为什么整数溢出“环绕”

原始的PDF

不,它不打印只有零。

改变它,你会看到会发生什么。

  int k = 50; while (true){ i = i + i; System.out.println(i); k--; if (k<0) break; } 

发生什么叫做溢出。

 static int i = 1; public static void main(String[] args) throws InterruptedException { while (true){ i = i + i; System.out.println(i); Thread.sleep(100); } } 

输出:

 2 4 8 16 32 64 ... 1073741824 -2147483648 0 0 when sum > Integer.MAX_INT then assign i = 0; 

因为我没有足够的声望,所以我不能在控制输出中用C语言输出同一个程序的输出图片,你可以尝试一下,看看它实际上打印了32次,然后如上所述,由于溢出i = 1073741824 + 1073741824更改为-2147483648,又一个添加超出int的范围,并变为

 #include<stdio.h> #include<conio.h> int main() { static int i = 1; while (true){ i = i + i; printf("\n%d",i); _getch(); } return 0; } 

i的值使用固定数量的二进制数字存储在内存中。 当一个号码需要比可用的更多的数字时,只有最低的数字被存储(最高的数字丢失)。

i加到自身和把i乘以2相同。 就像十进制数字乘以十的数字一样,可以通过向左滑动每个数字并将右边的数字设置为零,以二进制表示法将数字乘以二来执行。 这增加了一个数字在右侧,所以一个数字在左侧丢失。

这里的起始值是1,所以如果我们用8位数来存储i (例如),

  • 经过0次迭代后,值为00000001
  • 经过1次迭代后,值为00000010
  • 2次迭代后,值为00000100

依此类推,直到最后的非零步

  • 经过7次迭代后,值为10000000
  • 经过8次迭代后,值为00000000

无论分配多less个二进制数字来存储号码,不pipe起始值是什么,最后所有的数字都会丢失,因为它们被推到左边。 在这之后,继续加倍数字不会改变数字 – 它仍然会以全零表示。

这是正确的,但经过31次迭代,1073741824 + 1073741824不能正确计算,之后只打印0。

你可以重构使用BigInteger,所以你的无限循环将正常工作。

 public class Mathz { static BigInteger i = new BigInteger("1"); public static void main(String[] args) { while (true){ i = i.add(i); System.out.println(i); } } } 

为了debugging这种情况,最好减less循环中的迭代次数。 使用这个而不是你的while(true)

 for(int r = 0; r<100; r++) 

然后你可以看到它以2开始,并将值翻倍,直到它导致溢出。

我会用一个8位的数字来说明,因为它可以在一个很短的空间里完整的描述。 hex数字以0x开头,而二进制数字以0b开头。

8位无符号整数的最大值是255(0xFF或0b11111111)。 如果添加1,通常会得到:256(0x100或0b100000000)。 但是由于位数太多(9),所以超过了最大值,所以第一个部分刚刚被丢弃,使得0有效(0x(1)00或0b(1)00000000,但是1丢弃)。

所以当你的程序运行时,你会得到:

 1 = 0x01 = 0b1 2 = 0x02 = 0b10 4 = 0x04 = 0b100 8 = 0x08 = 0b1000 16 = 0x10 = 0b10000 32 = 0x20 = 0b100000 64 = 0x40 = 0b1000000 128 = 0x80 = 0b10000000 256 = 0x00 = 0b00000000 (wraps to 0) 0 + 0 = 0 = 0x00 = 0b00000000 0 + 0 = 0 = 0x00 = 0b00000000 0 + 0 = 0 = 0x00 = 0b00000000 ... 

inttypes的最大十进制文字是2147483648 (= 2 31 )。 从0到2147483647的所有十进制文字可能出现在可能出现的整型文字的任何位置,但文字2147483648可能只出现在一元否定运算符 – 的操作数中。

如果整数加法溢出,那么结果是math和的低位,如用一些足够大的二进制补码格式表示的那样。 如果发生溢出,则结果的符号与两个操作数值的math和的符号不同。

之所以没有看到较低的数字,是因为当它开始写入输出时,它已经超过了int的范围,有些是由于Java的慢速特性造成的ABCD分析/ JIT。

http://reverseblade.blogspot.com/2009/02/c-versus-c-versus-java-performance.html

我敢打赌,如果你添加了一个内存屏障或者打电话给'睡眠'或者声明int为volatile那么你会在更低的范围内看到更多的数字。

为什么0 语法上有效?

为什么这行在JavaScript中有效?

var a = 0[0]; 

之后, aundefined

当你做0[0] ,JS解释器会将第一个0变成一个Number对象,然后尝试访问那个undefined对象的[0]属性。

没有语法错误,因为在此上下文中语言语法允许属性访问语法0[0] 。 这个结构(使用Javascript语法中的术语)是NumericLiteral[NumericLiteral]

ES5 ECMAScript规范的第A.3节中的语言语法的相关部分是这样的:

 Literal :: NullLiteral BooleanLiteral NumericLiteral StringLiteral RegularExpressionLiteral PrimaryExpression : this Identifier Literal ArrayLiteral ObjectLiteral ( Expression ) MemberExpression : PrimaryExpression FunctionExpression MemberExpression [ Expression ] MemberExpression . IdentifierName new MemberExpression Arguments 

所以,可以通过这个过程跟随语法:

 MemberExpression [ Expression ] PrimaryExpression [ Expression ] Literal [ Expression ] NumericLiteral [ Expression ] 

而且,同样的Expression最终也可以是NumericLiteral所以在遵循语法之后,我们看到这是允许的:

 NumericLiteral [ NumericLiteral ] 

这意味着0[0]是语法的允许部分,因此不包含SyntaxError。


然后,在运行时,只要您从中读取的源是对象或者隐式转换为对象,就可以读取不存在的属性(只读为undefined的属性)。 而且,数字文字确实有一个隐式转换为一个对象(一个Number对象)。

这是Javascript常常未知的特性之一。 JavaScript中的NumberBooleanStringtypes通常在内部存储为基元(不是完整的对象)。 这些是一个紧凑的,不可变的存储表示(可能这样做是为了实现效率)。 但是,JavaScript希望你能够像对象一样使用属性和方法来处理这些基元。 所以,如果你试图访问一个不直接被基元支持的属性或者方法,那么Javascript会暂时将这个基元强制转换为一个适当types的对象,其值被设置为基元的值。

当在像0[0]这样的基元上使用类似对象的语法时,解释器会将其视为对基元的属性访问。 它对此的回应是取第一个0数字原语并将其强制为一个完整的Number对象,然后可以访问其上的[0]属性。 在这个特定的情况下,Number对象的[0]属性是undefined ,这就是为什么这是从0[0]得到的值。

这里是一个关于自动转换为对象处理属性的对象的文章:

Javascript原语的秘密生活


以下是ECMAScript 5.1规范的相关部分:

9.10 CheckObjectCoercible

如果值undefined ,则抛出TypeError,否则返回true

在这里输入图像说明

11.2.1属性访问器

  1. 让baseReference是评估MemberExpression的结果。
  2. 让baseValue成为GetValue(baseReference)。
  3. 让propertyNameReference是评估Expression的结果。
  4. 让propertyNameValue是GetValue(propertyNameReference)。
  5. 调用CheckObjectCoercible(baseValue)。
  6. 让propertyNameString是ToString(propertyNameValue)。
  7. 如果正在评估的句法生成被包含在严格的模式代码中,那么严格要求是真实的,否则严格是错误的。
  8. 返回基types值为baseValue,引用名称为propertyNameString,严格模式标志严格的Referencetypes的值。

这个问题的执行部分是上面的步骤#5。

8.7.1 GetValue(V)

这里描述了当被访问的值是一个属性引用时,它调用ToObject(base)来获取任何原语的对象版本。

9.9 ToObject

这将描述如何将BooleanNumberString基元转换为相应地设置了[[PrimitiveValue]]内部属性的对象forms。


作为一个有趣的testing,如果代码是这样的:

 var x = null; var a = x[0]; 

它仍然不会在parsing时抛出一个SyntaxError,因为这在技术上是合法的语法,但是它会在运行时在运行时抛出一个TypeError,因为当上面的Property Accessors逻辑应用到x的值时,它会调用CheckObjectCoercible(x)或调用ToObject(x) ,如果xnullundefined话,这两者都会抛出TypeError。

像大多数编程语言一样,JS使用语法来分析代码并将其转换为可执行forms。 如果语法中没有可应用于特定代码块的规则,则会引发SyntaxError。 否则,代码被认为是有效的,无论是否合理。

JS语法的相关部分是

 Literal :: NumericLiteral ... PrimaryExpression : Literal ... MemberExpression : PrimaryExpression MemberExpression [ Expression ] ... 

由于0[0]符合这些规则,因此它被认为是有效的expression式。 是否正确 (例如在运行时不会发生错误)是另一回事,但是是的。 这是JS如何评估expression式someLiteral[someExpression]

  1. 评估一些someExpression (可以是任意复杂的)
  2. 将文字转换为相应的对象types(数字文字=> Number ,string=> String等)
  3. 结果(2)调用结果(1)的get property操作,
  4. 丢弃结果(2)

所以0[0]被解释为

 index = 0 temp = Number(0) result = getproperty(temp, index) // it's undefined, but JS doesn't care delete temp return result 

下面是一个有效不正确的expression式的例子:

 null[0] 

它的分析很好,但是在运行时,解释器在步骤2上失败(因为null不能被转换为对象),并引发运行时错误。

有些情况下,你可以有效地在Javascript中下标一个数字:

 -> 0['toString'] function toString() { [native code] } 

虽然不是很明显,为什么你会想要这样做,在JavaScript中下标相当于使用虚线符号(尽pipe点符号限制您使用标识符作为键)。

我只想指出,这是有效的语法是不是以任何方式独特的Javascript。 大多数语言将有一个运行时错误或types错误,但这不是一个语法错误。 在许多情况下,Javascript会select返回undefined,在这种情况下,另一种语言可能会引发exception,包括下标没有给定名称属性的对象时。

语法不知道expression式的types(即使是像数字文字这样简单的expression式),也可以让任何运算符应用于任何expression式。 例如,尝试下标undefinednull会导致Javascript中的TypeError 。 这不是一个语法错误 – 如果这从来没有执行过(在if语句的错误一侧),它不会造成任何问题,而语法错误是定义总是在编译时捕获(eval,Function等,都算作编译)。

因为它是有效的语法,甚至有效的代码来解释。 你可以尝试访问任何对象的任何属性(在这种情况下,0将被转换为一个数字对象),如果它存在,它会给你的价值,否则未定义。 尝试访问未定义的属性不起作用,所以0 [0] [0]会导致运行时错误。 这仍然被归类为有效的语法。 什么是有效的语法和什么不会导致运行时/编译时错误是有区别的。

不仅语法有效,结果也不一定是undefined尽pipe在大多数情况下,如果不是所有的理性情况。 JS是最纯粹的面向对象语言之一。 大多数所谓的OO语言都是面向类的,就是说你不能改变一次创build的对象的forms(与类绑定),而只能改变对象的状态。 在JS中,您可以更改状态以及对象的forms,而且这比您想象的更频繁。 这种能力使得一些相当模糊的代码,如果你滥用它。 数字是不变的,所以你不能改变对象本身,不是它的状态,也不是forms,所以你可以做

 0[0] = 1; 

这是一个有效的赋值expression式,返回1但实际上并不分配任何东西,数字0是不可变的。 这本身有点奇怪。 您可以拥有一个有效且正确的(可执行的)assingmentexpression式,它不分配任何内容(*)。 然而,数字的types是一个可变的对象,所以你可以改变types,并且改变将沿着原型链级联。

 Number[0] = 1; //print 1 to the console console.log(0[0]); //will also print 1 to the console because all integers have the same type console.log(1[0]); 

当然这与理智的使用类别相去甚远,但是指定了语言来允许这样做,因为在其他情况下,扩展对象的能力实际上是非常有意义的。 这是如何jQuery插件钩入jQuery对象举例。

(*)它确实将值1赋值给一个对象的属性,但是不能引用这个(transcient)对象,因此它将在nexx GC pass中收集

在JavaScript中,一切都是对象,所以当解释器parsing它时,它将0视为对象,并尝试返回0作为属性。 当您尝试访问true或“”(空string)的第0个元素时,会发生同样的事情。

即使你设置0 [0] = 1,它也会在内存中设置属性和值,但是当你访问0的时候,它会被视为一个数字(不要把Object当作数字来对待)。

从列表中删除无值,而不删除0值

这是我的开始。

我的列表

L = [0, 23, 234, 89, None, 0, 35, 9] 

当我运行这个:

 L = filter(None, L) 

我得到这个结果

 [23, 234, 89, 35, 9] 

但这不是我所需要的,我真正需要的是:

 [0, 23, 234, 89, 0, 35, 9] 

因为我正在计算数据的百分位数,而且0有很大的差别。

如何从列表中删除None值而不删除0值?

 >>> L = [0, 23, 234, 89, None, 0, 35, 9] >>> [x for x in L if x is not None] [0, 23, 234, 89, 0, 35, 9] 

只是为了好玩,下面是如何在不使用lambda情况下调整filter来做到这一点(我不会推荐这个代码 – 这只是为了科学目的)

 >>> from operator import is_not >>> from functools import partial >>> L = [0, 23, 234, 89, None, 0, 35, 9] >>> filter(partial(is_not, None), L) [0, 23, 234, 89, 0, 35, 9] 

FWIW,Python 3使这个问题变得简单:

 >>> L = [0, 23, 234, 89, None, 0, 35, 9] >>> list(filter(None.__ne__, L)) [0, 23, 234, 89, 0, 35, 9] 

在Python 2中,您将使用列表理解来代替:

 >>> [x for x in L if x is not None] [0, 23, 234, 89, 0, 35, 9] 

对于Python 2.7(请参阅Raymond的答案,对于Python 3等效):

想要知道是否“不是无”在python(和其他OO语言)中是如此常见,在我的Common.py(我用“from common import *”导入到每个模块)中,我包括这些行:

 def exists(it): return (it is not None) 

然后,从列表中删除无元素,只需执行:

 filter(exists, L) 

我觉得这比阅读相应的列表更容易阅读(Raymond表示,他的Python 2版本)。

使用列表理解这可以做到如下:

 l = [i for i in list if i is not None] 

l的值是:

 [0, 23, 234, 89, 0, 35, 9] 

@jamylak答案是相当不错的,但是如果你不想为了完成这个简单的任务而导入几个模块,那就写下你自己的lambda

 >>> L = [0, 23, 234, 89, None, 0, 35, 9] >>> filter(lambda v: v is not None, L) [0, 23, 234, 89, 0, 35, 9] 

迭代空间 ,使用可能是一个问题。 在不同情况下,configuration文件可能显示为“更快”和/或“更less内存”密集。

 # first >>> L = [0, 23, 234, 89, None, 0, 35, 9, ...] >>> [x for x in L if x is not None] [0, 23, 234, 89, 0, 35, 9, ...] # second >>> L = [0, 23, 234, 89, None, 0, 35, 9] >>> for i in range(L.count(None)): L.remove(None) [0, 23, 234, 89, 0, 35, 9, ...] 

一种方法(同样由@jamylak , @ Raymond Hettinger和@Diptobuild议 )在内存中创build一个重复列表,这对于包含less量None条目的大型列表来说可能是昂贵的。

第二种方法通过列表一次,然后再次每次直到达到None 。 这可能是更less的内存密集型,并且这个列表会变小。 列表大小的减less可能会加速前面的大量None条目,但最糟糕的情况是,如果大量的None条目在后面。

如果列表的一部分分配给每个处理元素, for循环方法可以并行化。 list理解方法也可以通过分割来并行化,以限制内存中的重复。

试图迭代列表并删除None条目变得复杂,因为元素被删除时列表收缩。 同样的问题(以及正常的并行编程问题)会影响并行化的任何尝试。

在一般情况下,select任何一种方法都可能无关紧要。 它变得更多的符号的偏好。

 from operator import is_not from functools import partial filter_null = partial(filter, partial(is_not, None)) # A test case L = [1, None, 2, None, 3] L = list(filter_null(L)) 

说清单如下所示

 iterator = [None, 1, 2, 0, '', None, False, {}, (), []] 

这将只返回那些bool(item) is True

 print filter(lambda item: item, iterator) # [1, 2] 

这相当于

 print [item for item in iterator if item] 

只是过滤无:

 print filter(lambda item: item is not None, iterator) # [1, 2, 0, '', False, {}, (), []] 

相当于:

 print [item for item in iterator if item is not None] 

获取所有评估为False的项目

 print filter(lambda item: not item, iterator) # Will print [None, '', 0, None, False, {}, (), []] 

如果这是所有列表,你可以修改先生@雷蒙德的答案

对于python 2 L = [ [None], [123], [None], [151] ] no_none_val = list(filter(None.__ne__, [x[0] for x in L] ) )

no_none_val = [x[0] for x in L if x[0] is not None] """ Both returns [123, 151]"""

如果variables不是None >>,则List中的variables<< list_indice [0]

此解决scheme使用而不是:

 value = None while value in yourlist: yourlist.remove(value) 

是否有可能通过减去两个不相等的浮点数来得到0?

在下面的例子中是否有可能被0(或者无穷)分割?

public double calculation(double a, double b) { if (a == b) { return 0; } else { return 2 / (a - b); } } 

在正常情况下,当然不会。 但是如果ab非常接近,由于计算精度会导致(ab)0

请注意,这个问题是针对Java的,但我认为它将适用于大多数编程语言。

在Java中,如果a != b ,则a - b永远不会等于0 。 这是因为Java要求支持非规格化数字的IEEE 754浮点运算。 从规格 :

特别是,Java编程语言要求支持IEEE 754非规格化浮点数和逐渐下溢,这使得更容易certificate特定数值algorithm的理想特性。 如果计算结果是非规格化的数字,则浮点运算不会“清零”。

如果一个FPU使用非规格化的数字 ,减去不相等的数字永远不会产生零(不同于乘法),也可以看到这个问题 。

对于其他语言,这取决于。 例如,在C或C ++中,IEEE 754支持是可选的。

也就是说,expression式2 / (a - b)可能溢出,例如用a = 5e-308b = 4e-308

作为一个解决方法,以下是什么?

 public double calculation(double a, double b) { double c = a - b; if (c == 0) { return 0; } else { return 2 / c; } } 

这样你就不依赖任何语言的IEEE支持。

无论a - b的值如何,你都不会得到一个除数,因为浮点数除以0不会引发exception。 它返回无限。

现在, a == b将返回true的唯一方法是如果ab包含完全相同的位。 如果它们的差别只是最低位,那么它们之间的差异将不是0。

编辑:

正如Bathsheba正确评论的那样,有一些例外:

  1. “不是一个数字比较”与自己的假,但将具有相同的位模式。

  2. -0.0被定义为与+0.0相比较,并且它们的位模式是不同的。

所以如果ab都是Double.NaN ,你将会到达else子句,但是由于NaN - NaN也返回NaN ,所以你不会被零除。

在这里没有可能发生零除的情况。

SMT Solver Z3支持精确的IEEE浮点运算。 让我们问Z3find数字ab ,使a != b && (a - b) == 0

 (set-info :status unknown) (set-logic QF_FP) (declare-fun b () (FloatingPoint 8 24)) (declare-fun a () (FloatingPoint 8 24)) (declare-fun rm () RoundingMode) (assert (and (not (fp.eq ab)) (fp.eq (fp.sub rm ab) +zero) true)) (check-sat) 

结果是UNSAT 。 没有这样的号码。

上面的SMTLIBstring还允许Z3select任意的舍入模式( rm )。 这意味着结果适用于所有可能的舍入模式(其中有五个)。 结果还包括任何variables可能是NaN或无限的可能性。

a == b被实现为fp.eq质量,使得+0f-0f相等。 与零的比较也使用fp.eq来实现。 既然这个问题的目的是为了避免零分,这是一个适当的比较。

如果使用按-0f来实现相等性testing,则+0f-0f将是使a - b为零的一种方式。 这个答案的不正确的以前的版本包含关于好奇的情况的模式细节。

Z3 Online还不支持FPA理论。 这个结果是使用最新的不稳定分支获得的。 它可以使用.NET绑定进行复制,如下所示:

 var fpSort = context.MkFPSort32(); var aExpr = (FPExpr)context.MkConst("a", fpSort); var bExpr = (FPExpr)context.MkConst("b", fpSort); var rmExpr = (FPRMExpr)context.MkConst("rm", context.MkFPRoundingModeSort()); var fpZero = context.MkFP(0f, fpSort); var subExpr = context.MkFPSub(rmExpr, aExpr, bExpr); var constraintExpr = context.MkAnd( context.MkNot(context.MkFPEq(aExpr, bExpr)), context.MkFPEq(subExpr, fpZero), context.MkTrue() ); var smtlibString = context.BenchmarkToSMTString(null, "QF_FP", null, null, new BoolExpr[0], constraintExpr); var solver = context.MkSimpleSolver(); solver.Assert(constraintExpr); var status = solver.Check(); Console.WriteLine(status); 

使用Z3来回答IEEE浮动问题是很好的,因为很难忽视这些情况(如NaN-0f+-inf ),并且可以提出任意的问题。 不需要解释和引用规范。 你甚至可以问混合浮点数和整数问题,比如“这个特定的int log2(float)algorithm是否正确?”。

提供的函数确实可以返回无穷大:

 public class Test { public static double calculation(double a, double b) { if (a == b) { return 0; } else { return 2 / (a - b); } } /** * @param args */ public static void main(String[] args) { double d1 = Double.MIN_VALUE; double d2 = 2.0 * Double.MIN_VALUE; System.out.println("Result: " + calculation(d1, d2)); } } 

输出Result: -InfinityResult: -Infinity

当分割的结果大到以双倍存储时,即使分母不为零,也返回无穷大。

在符合IEEE-754的浮点实现中,每种浮点types都可以保存两种格式的数字。 一个(“归一化”)被用于大多数浮点值,但是它能够表示的第二小数字只比最小值大一点点,所以它们之间的差别不能以相同的格式来表示。 另一种(“非规范化”)格式仅用于非常小的数字,不能用第一种格式表示。

处理非规格化浮点格式的电路是昂贵的,并不是所有的处理器都包含它。 一些处理器提供了一个select,要么在真正的小数字上进行操作比在其他数值上的操作慢得多,要么让处理器简单地把规格化格式太小的数字视为零。

Java规范意味着实现应该支持非规范化的格式,即使在这样做会使代码运行更慢的机器上。 另一方面,有些实现可能会提供一些选项,以允许代码运行得更快,以交换稍微草率的值处理,这对大多数目的来说太小了(在值太小而不重要的情况下,可能会令人烦恼,因为用它们计算需要十倍的时间,所以在许多实际情况下,清零比慢而精确的算术更有用。

在IEEE 754之前的旧时代,a = b并不意味着ab!= 0,反之亦然。 这是首先创buildIEEE 754的原因之一。

用IEEE 754 几乎可以保证。 C或C ++编译器允许以比所需更高的精度执行操作。 所以如果a和b不是variables而是expression式,那么(a + b)!= c并不意味着(a + b) – c!= 0,因为a + b可以以更高的精度计算一次,更高的精度。

许多FPU可以切换到不返回非规格化数字的模式,而是将其replace为0.在该模式下,如果a和b是微小的归一化数字,其差值小于最小归一化数字但大于0, != b也不能保证== b。

“从不比较浮点数”是货物崇拜节目。 在有口头禅的人中,“你需要一个小数”,大多数人都不知道如何正确地select这个小数。

你不应该比较平等或漂浮的比赛。 因为,你不能真正保证你分配给float或double的数字是确切的。

为了比较花车平等,您需要检查值是否“足够接近”到相同的值:

 if ((first >= second - error) || (first <= second + error) 

我可以想到一个你可能会导致这种情况发生的情况。 这里有一个基于10的类似的例子 – 当然,这实际上会发生在基数2。

浮点数或多或less以科学记数法存储 – 也就是说,不是看35.2,而是存储的数字更像3.52e2。

想象一下,为了方便起见,我们有一个浮点运算单元,以10为基数运行,并具有3位精度。 当你从10.0减去9.99时会发生什么?

1.00e2-9.99e1

转移给每个值相同的指数

1.00e2-0.999e2

舍入为3位数字

1.00e2-1.00e2

呃哦!

这是否会发生最终取决于FPUdevise。 由于double的指数范围非常大,所以硬件必须在某个点进行内部舍入,但是在上面的情况下,内部只需要一个额外的数字就可以避免任何问题。

基于@malarres回应和@Taemyr评论,这是我的小贡献:

 public double calculation(double a, double b) { double c = 2 / (a - b); // Should not have a big cost. if (isnan(c) || isinf(c)) { return 0; // A 'whatever' value. } else { return c; } } 

我的意思是说:最简单的方法就是知道这个划分的结果是nan还是inf就是实际的划分。

除以零是不明确的,因为正数的极限趋于无穷大,负数的极限趋于负无穷大。

不知道这是C ++还是Java,因为没有语言标记。

 double calculation(double a, double b) { if (a == b) { return nan(""); // C++ return Double.NaN; // Java } else { return 2 / (a - b); } } 

核心问题是当你有十进制“太多”的时候,双精度(又名浮点数,或者math语言中的实数)的计算机表示是错误的,比如当你处理不能被写成数字值的double时pi或1/3的结果)。

所以a == b不能用a和b的任何double值来完成,当a = 0.333和b = 1/3时如何处理a == b? 根据您的操作系统与FPU与数量与语言与3之后的0计数,您将有真或假。

无论如何,如果你在计算机上进行“双值计算”,你必须处理的准确性,所以,而不是做a==b ,你必须做absolute_value(ab)<epsilon ,而epsilon是相对于你正在build模那个时间在你的algorithm中。 你的双重比较你不能有一个epsilon价值。

简而言之,当你键入一个== b时,你有一个mathexpression式,不能在计算机上转换(对于任何浮点数)。

PS:哼,我在这里回答的一切,或多或less都在别人的回应和评论中。

为什么用0初始化纯虚函数?

我们总是声明一个纯虚函数:

virtual void fun () = 0 ; 

即,它总是分配给0。

我的理解是,这是初始化这个函数的Vtable条目为NULL和任何其他值在这里导致编译时错误。 这种理解是否正确?

原因=0的原因是,Bjarne Stroustrup不认为他可以得到另一个关键字,比如在实现该function时通过C ++社区的“纯”。 这在他的书“ The Design&Evolution of C ++ ”第13.2.3节中有描述:

好奇= 0语法被选中…因为当时我看不到接受新关键字的机会。

他还明确指出,这不需要将vtable条目设置为NULL,并且这样做不是实现纯虚函数的最佳方式。

与C ++devise中的大多数“为什么”问题一样,首先要看的是Bjarne Stroustrup 1 的“C ++的devise与发展”

奇怪的=0语法被select,而不是引入一个新的关键字pureabstract的明显的替代scheme,因为当时我看不到接受一个新的关键字的机会。 如果我build议pure ,发行版2.0将没有抽象类发行。 鉴于更好的语法和抽象类之间的select,我select了抽象类。 我没有冒险拖延和招致一些pure战斗,而是使用传统的C和C ++约定来使用0来表示“不存在”。 =0语法符合我的观点,即函数体是一个函数的初始化方法,也是将虚拟函数集作为函数指针向量来实现的(简单的,但通常是足够的)视图。 […]

1§13.2.3语法

C ++标准的9.2节给出了类成员的语法。 它包括这个生产:

 pure-specifier: = 0 

价值没有什么特别之处。 “= 0”只是说“这个函数是纯虚拟的”的语法。 它与初始化或空指针或数字零值无关,尽pipe与这些事物的相似性可能具有助记符值。

我不确定这背后是否有任何意义。 这只是语言的语法。

C ++一直避免引入新的关键字,因为新的保留字破坏了使用这些字作为标识符的旧程序。 人们经常看到,尽可能尊重旧代码的语言的优势之一。

=0语法可能确实已经被选中,因为它类似于将vtable条目设置为0 ,但是这纯粹是符号的。 (大多数编译器将这样的vtable条目分配给一个在中止程序之前发出错误的存根)。语法主要是因为它之前没有用到任何东西而被选中,并且保存了一个新的关键字。

C ++必须有一种方法来区分纯虚函数和正常虚函数的声明。 他们select使用= 0语法。 他们可以通过添加纯关键字来轻松完成相同的操作。 但是C ++非常不愿意添加新的关键字,并且倾向于使用其他机制来引入特性。

在这种情况下,什么都不是“初始化”或“分配”零。 = 0只是一个由=0标记组成的语法结构,它与初始化或赋值绝对没有关系。

它与“vtable”中的任何实际值没有关系。 C ++语言没有“vtable”或任何这样的概念。 各种“vtables”只不过是具体实现的细节。

我记得读到,有趣的语法的理由是,比引入另一个可以做同样事情的关键字更容易(在标准接受方面)。

我相信这是在Bjarne Stroustrup的“C ++devise与进化”一书中提到的。

我会假设这只是C ++语法的一部分。 我不认为编译器如何实现这个给定的特定二进制格式有任何限制。 你对于早期的C ++编译器可能是正确的。

= 0声明一个纯虚函数

我们知道这是为了将这个函数的vtable条目初始化为NULL,而这里的任何其他值都会导致编译时错误

我不认为这是真的。 这只是特殊的语法。 该表是实现定义的。 没有人说一个纯成员的vtable条目必须在构build时实际上归零(尽pipe大多数编译器处理类似的vtable)。

那么,你也可以初始化vtable条目来指向一个实际的函数“

  virtual void fun() { //dostuff() } 

看起来很直观,可以将vtable条目定义为指向无处(0)或指向函数。 让你指定自己的值可能会导致它指向垃圾而不是一个函数。 但这就是为什么“= 0”是允许的,“= 1”不是。 我怀疑尼尔·巴特沃斯对于为什么使用“= 0”是正确的

初始化对象时{0}是什么意思?

{0}被用来初始化一个对象时,它是什么意思? 我无法在任何地方find任何对{0}引用,并且由于Google大括号的search没有帮助。

示例代码:

 SHELLEXECUTEINFO sexi = {0}; // what does this do? sexi.cbSize = sizeof(SHELLEXECUTEINFO); sexi.hwnd = NULL; sexi.fMask = SEE_MASK_NOCLOSEPROCESS; sexi.lpFile = lpFile.c_str(); sexi.lpParameters = args; sexi.nShow = nShow; if(ShellExecuteEx(&sexi)) { DWORD wait = WaitForSingleObject(sexi.hProcess, INFINITE); if(wait == WAIT_OBJECT_0) GetExitCodeProcess(sexi.hProcess, &returnCode); } 

没有它,上面的代码将在运行时崩溃。

这里发生了什么叫做聚合初始化。 以下是ISO规范第8.5.1节中的一个聚合的(缩写)定义:

聚合是一个没有用户声明构造函数的数组或类,没有私有或受保护的非静态数据成员,没有基类,也没有虚函数。

现在,使用{0}来初始化一个像这样的聚合,基本上就是把整个事情都弄成一团。 这是因为在使用聚合初始化时, 您不必指定所有成员 ,并且规范要求所有未指定的成员都被默认初始化,对于简单types,这意味着设置为0

这里是规范的相关引用:

如果列表中的初始化器数量less于聚合中的成员数量,那么未明确初始化的每个成员应该被默认初始化。 例:

 struct S { int a; char* b; int c; }; S ss = { 1, "asdf" }; 

初始化ss.a1ss.b"asdf"ss.cint()forms的expression式的值,即0

你可以在这里find关于这个主题的完整规范

有一点要注意的是,这种技术不会将填充字节设置为零。 例如:

 struct foo { char c; int i; }; foo a = {0}; 

不一样:

 foo a; memset(&a,0,sizeof(a)); 

在第一种情况下,c和i之间的填充字节未初始化。 你为什么在意? 那么,如果你将这些数据保存到磁盘或通过networking或其他方式发送,那么你可能会遇到安全问题。

请注意,一个空的聚合初始值设定项也可以用

 SHELLEXECUTEINFO sexi = {}; char mytext[100] = {}; 

在回答为什么ShellExecuteEx()崩溃时: SHELLEXECUTEINFO “sexi”结构有许多成员,你只是初始化其中的一部分。

例如,成员sexi.lpDirectory可能指向任何地方,但ShellExecuteEx()仍然会尝试使用它,因此你会得到一个内存访问冲突。

当你包含该行时:

 SHELLEXECUTEINFO sexi = {0}; 

在结构设置的其余部分之前,您要让编译器在初始化您感兴趣的特定结构成员之前将所有结构成员sexi.lpDirectory ShellExecuteEx()知道如果sexi.lpDirectory为零,则应该忽略它。

我也用它来初始化string,例如。

 char mytext[100] = {0}; 

对于C和C ++中的任何(完整对象)types, {0}都是有效的初始值设定项。 这是一个常用的习惯用来初始化一个对象为零 (阅读看看是什么意思)。

对于标量types(算术和指针types),大括号是不必要的,但它们是明确允许的。 引用ISO C标准的N1570草案第6.7.9节:

标量的初始值应该是一个单独的expression式,可以用大括号括起来。

它将对象初始化为零(整数为0 ,浮点为0.0 ,指针为空指针)。

对于非标量types(结构,数组,联合), {0}指定对象的第一个元素被初始化为零。 对于包含结构,结构数组等等的结构,这是recursion地应用的,所以第一个标量元素被设置为0,以适合于types。 和任何初始化器一样,任何未指定的元素都被设置为零。

中间括号( {} )可以省略; 例如这两个都是有效的和等价的:

 int arr[2][2] = { { 1, 2 }, {3, 4} }; int arr[2][2] = { 1, 2, 3, 4 }; 

这就是为什么您不必编写例如{ { 0 } }的types的第一个元素是非标量的。

所以这:

 some_type obj = { 0 }; 

是将obj初始化为零的简写方法,这意味着如果obj每个标obj都是整数,则为0如果是浮点,则为0如果是指针,则为空指针。

C ++的规则是相似的。

在你的具体情况下,因为你将值分配给sexi.cbSize等等,很显然SHELLEXECUTEINFO是一个结构或类types(或可能是一个联合,但可能不是),所以并不是所有这些都适用,但是因为我说{ 0 }是一个常用的习惯用法,可以用在更一般的情况下。

不是 (必然)等同于使用memset将对象的表示设置为全零位。 浮点0.0和空指针都不一定表示为全零位,并且{ 0 }初始化器不一定将填充字节设置为任何特定值。 但是在大多数系统中,它可能具有相同的效果。

我工作在C / C ++,但是IIRC已经有一段时间了,同样的捷径也可以用于数组。

我一直在想, 为什么你要用这样的东西

 struct foo bar = { 0 }; 

这里是一个testing用例来解释:

check.c

 struct f { int x; char a; } my_zero_struct; int main(void) { return my_zero_struct.x; } 

我用gcc -O2 -o check check.c ,然后用readelf -s check | sort -k 2输出符号表 readelf -s check | sort -k 2 (这是在x64系统上的ubuntu 12.04.2上的gcc 4.6.3)。 摘抄:

 59: 0000000000601018 0 NOTYPE GLOBAL DEFAULT ABS __bss_start 48: 0000000000601018 0 NOTYPE GLOBAL DEFAULT ABS _edata 25: 0000000000601018 0 SECTION LOCAL DEFAULT 25 33: 0000000000601018 1 OBJECT LOCAL DEFAULT 25 completed.6531 34: 0000000000601020 8 OBJECT LOCAL DEFAULT 25 dtor_idx.6533 62: 0000000000601028 8 OBJECT GLOBAL DEFAULT 25 my_zero_struct 57: 0000000000601030 0 NOTYPE GLOBAL DEFAULT ABS _end 

这里的重要部分是, my_zero_struct__bss_start之后。 C程序中的“.bss”部分是在调用main 之前设置为0的内存部分,参见.bss上的wikipedia 。

如果您将上面的代码更改为:

 } my_zero_struct = { 0 }; 

那么得到的“check”可执行文件看起来与ubuntu 12.04.2上的gcc 4.6.3编译器至less是一样的; my_zero_struct仍然位于.bss段,因此在调用main之前,它将自动初始化为零。

在注释中提示, memset可能初始化“full”结构也不是一个改进,因为.bss部分被完全清除,这也意味着“full”结构被设置为零。

C语言标准可能没有提到这一点,但在现实世界的C编译器中,我从来没有见过不同的行为。

{0}是一个匿名数组 ,其元素为0。

这用于使用0初始化数组中的一个或所有元素。

例如int arr [8] = {0};

在这种情况下,arr的所有元素将被初始化为0。

大小为0的数组

今天我偶然定义了一维的大小为0的二维数组,但我的编译器没有抱怨。 我发现下面这说明这是合法的,至less在gcc的情况下:

6.17长度为零的数组

不过,我对这个用法有两个问题:

首先,这是否被认为是良好的编程习惯? 如果是这样的话,那我们应该在什么时候在现实世界中使用

其次,我定义的数组是二维的,一维为0。 这与一维情况相同吗? 例如,

int s[0] int s[0][100] int s[100][0] 

它们在内存和编译器中都是一样的吗?

编辑:回复格雷格:我使用的编译器是gcc 4.4.5。 我对这个问题的意图是不依赖于编译器,但是如果有任何编译器具体的怪癖,也将有所帮助:)

提前致谢!

在C ++中,声明一个长度为零的数组是非法的。 因此,当您将代码绑定到特定的编译器扩展时,通常不会将其视为一种好的做法。 dynamic大小的数组的许多用途更好地replace为容器类,如std::vector

ISO / IEC 14882:2003 8.3.4 / 1:

如果存在常数expression式 (5.19),则它应该是一个整型常量expression式,其值应大于零。

但是,可以使用new[]dynamic分配一个长度为零的数组。

ISO / IEC 14882:2003 5.3.4 / 6:

直接新申报人的表述应具有整数或枚举types(3.9.1),并具有非负值。

我在ideone.com上运行这个程序

 #include <iostream> int main() { int a[0]; int b[0][100]; int c[100][0]; std::cout << "sizeof(a) = " << sizeof(a) << std::endl; std::cout << "sizeof(b) = " << sizeof(b) << std::endl; std::cout << "sizeof(c) = " << sizeof(c) << std::endl; return 0; } 

它把所有variables的大小都设为0。

 sizeof(a) = 0 sizeof(b) = 0 sizeof(c) = 0 

所以在上面的例子中,没有内存分配给abc

用gcc编译你的例子,他们三个都有sizeof 0,所以我会假定所有的这些都被编译器同等对待。

你的链接解释了一切。 当在编译时不知道struct的长度时,它们被用作struct中的最后一个字段。 如果您尝试在堆栈或其他声明中使用它们,您将最终覆盖下一个元素。

如何捕获这个错误:“注意:未定义的偏移量:0”

我想赶上这个错误:

$a[1] = 'jfksjfks'; try { $b = $a[0]; } catch (\Exception $e) { echo "jsdlkjflsjfkjl"; } 

编辑:事实上,我得到了以下行的错误: $parse = $xml->children[0]->children[0]->toArray();

您需要定义您的自定义error handling程序,如:

 <?php set_error_handler('exceptions_error_handler'); function exceptions_error_handler($severity, $message, $filename, $lineno) { if (error_reporting() == 0) { return; } if (error_reporting() & $severity) { throw new ErrorException($message, 0, $severity, $filename, $lineno); } } $a[1] = 'jfksjfks'; try { $b = $a[0]; } catch (Exception $e) { echo "jsdlkjflsjfkjl"; } 

你不能用try / catch块,因为这是一个错误,不是一个例外。

在使用之前总是尝试偏移:

 if( isset( $a[ 0 ] ) { $b = $a[ 0 ]; } 
 $a[1] = 'jfksjfks'; try { $offset = 0; if(isset($a[$offset])) $b = $a[$offset]; else throw new Exception("Notice: Undefined offset: ".$offset); } catch (Exception $e) { echo $e->getMessage(); } 

或者,没有创造一个非常暂时的例外的低效率:

 $a[1] = 'jfksjfks'; $offset = 0; if(isset($a[$offset])) $b = $a[$offset]; else echo "Notice: Undefined offset: ".$offset; 

我知道这是2016年,但万一有人得到这个职位。

您可以使用array_key_exists($index, $array)方法来避免发生exception。

 $index = 99999; $array = [1,2,3,4,5,6]; if(!array_key_exists($index, $array)) { //Throw myCustomException; } 

通常情况下,您无法使用try-catch块捕获通知。 但是,您可以将通知转换为例外! 使用这种方式:

 function get_notice($output) { if (($noticeStartPoint = strpos($output, "<b>Notice</b>:")) !== false) { $position = $noticeStartPoint; for ($i = 0; $i < 3; $i++) $position = strpos($output, "</b>", $position) + 1; $noticeEndPoint = $position; $noticeLength = $noticeEndPoint + 3 - $noticeStartPoint; $noticeMessage = substr($output, $noticeStartPoint, $noticeLength); throw new \Exception($noticeMessage); } else echo $output; } try { ob_start(); // Codes here $codeOutput = ob_get_clean(); get_notice($codeOutput); } catch (\Exception $exception) { // Catch (notice also)! } 

另外,您可以使用此function来捕捉警告。 只需将function名称更改为get_warning,然后将"<b>Notice</b>:"更改为"<b>Warning</b>:"

注意:函数会捕获一个无辜的输出,其中包含:

<B>注意</ b>的:

但是为了摆脱这个问题,简单地把它改为:

<B>注意:</ b>的

林肯定为什么错误抛出,但我修正了一些..

在html2pdf.class.php中

在2132行:

 //FIX: $ctop=$corr[$y][$x][2]<=count($sw)?$corr[$y][$x][2]:count($sw); $s = 0; for ($i=0; $i<$ctop; $i++) {$s+= array_key_exists($x+$i, $sw)? $sw[$x+$i]:0;} 

同样在2138行:

 //FIX: $ctop=$corr[$y][$x][2]<=count($sw)?$corr[$y][$x][2]:count($sw); for ($i=0; $i<$ctop; $i++) { 

数组$ sw没有$ corr [$ y] [$ x] [2]的键的问题,所以我修复了最大计数($ sw)的循环来修复..我不知道是否创build了另一个通用但我解决我的问题,我没有任何更多的错误..

所以我希望对你有用。 节拍调节器

为什么我只能得到清晰的版本0?

通常,第一个提交的版本应该从1开始。版本0与分支点相同。 但现在我得到一个唯一的版本0,这阻止我检查任何其他版本因为它警告我,分支已经创build。

如“在向源代码pipe理添加文件和目录之前”所述,版本0是一个占位符,标记给定分支中所有版本的开始:

在这里输入图像描述

如果撤消在新分支中签出的文件(在这种情况下,只剩下新创build的分支的版本0),则最终只能得到版本0。

关于分支,你可能会有像“ element already has a branch of type branch ”错误,但只有当服务器和客户端时间(时钟)不同步的问题 。

当你创build一个元素(或分支)时,ClearCase会创build版本0,通常会自动检出。 正如您所注意的,版本0始终为空或与分支版本相同。 简单地在版本1中检查就不会有任何问题。

请注意,分支是在您退房时创build的,而不是在您办理入住手续时创build的,因此您不应在办理登机手续时收到任何警告。 如果您发布确切的命令行和警告/错误,我们可能会帮助您更多。

也许可能是因为你在你的分支上创build了一个新的元素,而你的configuration规范中缺less“/ main / 0 -mkbranch”。

HTH。

双值返回0

这是一个例子:

Double d = (1/3); System.out.println(d); 

这将返回0,而不是0.33333 …因为它应该。

有人知道吗?

这是因为13在没有另外指定时被视为integers ,所以1/3计算为integer 0 ,然后将其转换为double 0 。 为了解决这个问题,试试(1.0/3) ,或者1D/3来明确说明你正在处理double值。

如果你想使用浮点除法来分割int ,那么你必须把int double

 double d = (double)intValue1 / (double)intValue2 

(实际上,我相信只有铸造intValue2应该足以让intValue1被自动double

除非您需要在对象意义上使用这些值,否则使用double而不是Double 。 注意Autoboxing的概念

什么,确切地说,“边际:0汽车;”需要工作?

我知道设置margin: 0 auto; 在一个元素上被用来居中它(左 – 右)。 但是,我知道元素及其父项必须符合一定的汽车边距标准才能工作,而我永远也看不到这个魔法的正确性。

所以我的问题很简单:在元素和它的父为了margin: 0 auto; ,必须设置什么样的CSS属性margin: 0 auto; 左右中心的孩子?

closures我的头顶上:

  1. 元素必须是块级别的,例如display: blockdisplay: table
  2. 元素不能浮动
  3. 该元素不得有固定或绝对的位置1

在别人的头顶上:

  1. 该元素必须具有非auto 2width

1 有一个例外:如果你的固定或绝对定位的元素已经left: 0; right: 0 left: 0; right: 0 , 它将以自动边距为中心 。

2 从技术上讲, margin: 0 auto的宽度是自动调整的,但是自动宽度优先于自动调整的宽度,所以自动调整边距会被清零,看起来好像“不起作用”。

在我头顶上,它需要一个width 。 您需要指定您正在居中的容器的宽度(而不是父宽度)。

我做了一个例子,所以你可以看到发生了什么,据我所知,这是你需要的一切:)

完整的规则:

  1. display: block width不自动)或display: table
  2. float: none
  3. position: relative

如果这个元素不是一个块元素,那么就从头开始吧。

然后给它一个宽度。

请转到我创buildjsFiddle的这个简单例子。 Hopefull很容易理解。 您可以使用包含网站宽度的wrapper div来居中alignment。 你必须把width的原因是,所以浏览器知道你不会液体布局。

它也将与display:table一起使用,在这种情况下是一个有用的显示属性,因为它不需要设置宽度。 (我知道这个post已经5岁了,但是对于路人来说还是相关的)

这是我的build议:

 First: 1. Add display: block or table 2. Add position: relative 3. Add width:(percentage also works fine) Second: if above trick not works then you have to add float:none; 

在我的猫的头顶,确保你试图居中的div没有设置为width: 100%

如果是这样,那么在子div上设置的规则是重要的。

也许有趣的是,你不必为<button>元素指定宽度来使其工作 – 只要确保它具有display:block : http : //jsfiddle.net/muhuyttr/

整数总是初始化为0?

在Objective-C中指望int总是被初始化为0是否安全?

更具体地说,当一个int ivars对象被新实例化时,假设它的ivars的值为0是否安全?

是的,类实例variables总是被初始化为0(或者nilNULL或者false ,这取决于确切的数据types)。 请参阅Objective-C 2.0编程语言 :

alloc方法为新对象的实例variablesdynamic分配内存,并将它们全部初始化为0-all,即除了将新实例连接到它的类的isavariables外。


编辑2013-05-08
苹果似乎已经删除了上面的文件(现在链接到Wayback Machine)。 使用Objective-C进行编程的(当前)活动文档包含类似的引用:

alloc方法还有另外一个重要的任务,就是通过将分配给对象属性的内存设置为零来清除内存。 这样可以避免以前存储的内存中包含垃圾的常见问题,但不足以完全初始化对象。


但是, 这只适用于一个类的实例variables; 在全球范围内宣布的PODtypes也是如此:

 // At global scope int a_global_var; // guaranteed to be 0 NSString *a_global_string; // guaranteed to be nil 

有一个例外,对于局部variables或者用malloc()或者realloc()分配的数据是正确的。 calloc()是真的,因为calloc()显式地将它分配的内存清零。

一个例外是,当启用自动引用计数(ARC)时,到Objective-C对象的堆栈指针被隐式地初始化nil ; 但是,明确地将它们初始化nil是个好习惯。 从过渡到ARC发行说明 :

堆栈variables初始化nil

使用ARC,强,弱和自动释放栈variables现在用nil隐式初始化

在C ++(和Objective-C ++中使用的C ++对象)中,类实例variables也不是零初始化的。 你必须在你的构造函数中明确地初始化它们。

我不认为你应该承担任何初始化值。 如果围绕“0”值构build逻辑,则应将其设置为确定。

是的,在C全局variables初始化为零。 在Objective-C中,即使局部variables也被初始化为零。 你可以依靠它。

检查浮点值是否等于0是否安全?

我知道你不能依赖于正常的双或十进制types值之间的平等,但我想知道如果0是一个特例。

虽然我可以理解0.00000000000001和0.00000000000002之间的不精确性,0本身似乎很难搞乱,因为它只是一无所获。 如果你什么都不准确,那不是什么了。

但是我不太了解这个话题,所以我不能说。

double x = 0.0; return (x == 0.0) ? true : false; 

这将永远回报真实?

当且仅当双variables的值恰好为0.0 (当然,在你的原始代码片段中,当然是这种情况)时,期望比较将是可靠的 。 这与==运算符的语义是一致的。 a == b表示“ a等于b ”。

这是不安全的 (因为它是不正确的 ),当纯math中相同的计算结果为零时,期望计算的结果在双(或者更一般地说,浮点)algorithm中为零。 这是因为当计算进行到底时,会出现浮点精度误差 – 这是math中实数运算中不存在的一个概念。

如果你需要做大量的“平等”比较,在.NET 3.5中编写一个辅助函数或扩展方法来比较是个好主意:

 public static bool AlmostEquals(this double double1, double double2, double precision) { return (Math.Abs(double1 - double2) <= precision); } 

这可以用以下方式:

 double d1 = 10.0 * .1; bool equals = d1.AlmostEquals(0.0, 0.0000001); 

对于你简单的例子,那个testing是可以的。 但是这个怎么样:

 bool b = ( 10.0 * .1 - 1.0 == 0.0 ); 

请记住.1是二进制中的重复小数,不能完全表示。 然后比较这个代码:

 double d1 = 10.0 * .1; // make sure the compiler hasn't optimized the .1 issue away bool b = ( d1 - 1.0 == 0.0 ); 

我会让你去testing一下,看看实际的结果:你更有可能记得那样。

从Double.Equals的MSDN条目:

比较中的精确度

应该谨慎使用Equals方法,因为两个值的不同精度可能导致两个明显相等的值不相等。 以下示例报告Double值.3333和1除以3返回的Double不相等。

一个推荐的技术不是比较平等,而是涉及定义两个值之间的可接受的差值余量(例如其中一个值的0.01%)。 如果两个值之间的差值的绝对值小于或等于该裕度,则差异可能是由于精度的差异,因此这些值可能是相等的。 以下示例使用此技术来比较.33333和1/3,前面的代码示例发现不相等的两个Double值。

另请参阅Double.Epsilon 。

当你比较不同types的浮点值实现时,问题就出现了,例如比较float和double。 但是相同的types,这不应该是一个问题。

 float f = 0.1F; bool b1 = (f == 0.1); //returns false bool b2 = (f == 0.1F); //returns true 

问题是,程序员有时忘记了隐式types转换(双重浮动)正在发生的比较,它会导致一个错误。

如果数字直接分配给浮点数或双精度浮点数,那么可以安全地testing零点或任何整数,可以用53位表示浮点数,也可以用24位表示浮点数。

或者换句话说,你总是可以把整数值赋给一个double,然后再把double赋值给同一个整数,并保证它是相等的。

你也可以从分配一个整数开始,通过坚持加,减或整数乘以简单的比较继续工作(假设结果是less于24位的浮点数和双精度的53位)。 所以你可以在一定的控制条件下把漂浮和双打当作整数。

不,不行。 所谓的非规格化值(subnormalized),当被比较等于0.0时,将比较为假(非零),但是当在等式中使用时将被归一化(变为0.0)。 因此,将其作为避免被零除的机制是不安全的。 相反,加1.0和比较1.0。 这将确保所有的低于正常值被视为零。

实际上,我认为使用下面的代码来比较一个double值和0.0是比较好的:

 double x = 0.0; return (Math.Abs(x) < double.Epsilon) ? true : false; 

同样的浮动:

 float x = 0.0f; return (Math.Abs(x) < float.Epsilon) ? true : false; 

0是十进制文字还是八进制文字?

零总是零,所以没关系。 但在最近与朋友的讨论中,他说八进制文字今天几乎没有用。 然后它觉得我实际上几乎所有的整数字面值八进制的,即0

根据C ++语法, 0是一个八进制文字吗? 标准说什么?

是的, 0是C ++中的八进制文字

根据C ++标准:

2.14.2整数文字[lex.icon]

 integer-literal: decimal-literal integer-suffixopt octal-literal integer-suffixopt hexadecimal-literal integer-suffixopt decimal-literal: nonzero-digit decimal-literal digit octal-literal: 0 <--------------------<Here> octal-literal octal-digit 

任何前缀为0整数值都是八进制值。 即:01是八进制数1,010是八进制数10,它是十进制数8,0是八进制数0(十进制数和其他0)。

所以是的,'0'是一个八进制。

这是@ Als的答案中的语法片段的纯英文翻译:-)


0x的整数不是0为前缀。 0x是一个明确不同的前缀。 显然有人不能做这个区别。

按照同样的标准,如果我们继续:

  integer-literal: decimal-literal integer-suffixopt octal-literal integer-suffixopt hexadecimal-literal integer-suffixopt decimal-literal: nonzero-digit <<<---- That's the case of no prefix. decimal-literal digit-separatoropt digit octal-literal: 0 <<<---- '0' prefix defined here. octal-literal digit-separatoropt octal-digit <<<---- No 'x' or 'X' is allowed here. hexadecimal-literal: 0x hexadecimal-digit <<<---- '0x' prefix defined here 0X hexadecimal-digit <<<---- And here. hexadecimal-literal digit-separatoropt hexadecimal-digit 

显然,从零开始的所有整数文字实际上都是八进制的。 这意味着它也包括0。 由于零为零,所以这没什么区别。 但不知道这个事实会伤害你。

当我试图编写一个程序将二进制数转换为十进制和hex输出时,我意识到了这一点。 每当我给出一个从零开始的数字,我得到了错误的输出(例如,012 = 10,而不是12)。

知道这些信息是很好的,所以你不会犯同样的错误。

不透明度:0与可见性完全相同:隐藏

如果是这样,它是否有效地反对visibility属性?

(我知道Internet Explorer不支持这个CSS2属性。)
布局引擎的比较

另请参阅:可见性:hidden和display:none之间有什么区别?

以下是各种答案的核实信息汇编。

每个CSS属性都是​​独一无二的。 除了渲染元素不可见外,还具有以下附加效果:

  1. 折叠元素通常会占据的空间
  2. 响应事件 (例如,点击,按键)
  3. 参与制表
                     折叠事件taborder
不透明度:0否是是
能见度:隐藏否否否
知名度:崩溃*否否
显示:无是否否

 *是在表格元素内,否则

没有。

具有不透明度的元素创build新的堆叠上下文。

此外,CSS规范没有定义这一点,但opacity:0的元素是可点击的,而具有visibility:hidden元素则不是。

不,不是的。 有一个很大的区别。 它们是相似的,因为如果可见性被隐藏或者不透明度为0,则可以通过该元素看到

不透明度:0你不能点击它后面的元素。

可见性:隐藏您可以点击它后面的元素。

我不完全确定,但这是我如何跨浏览器的透明度:

 opacity: 0.6; -moz-opacity: 0.6; filter: alpha(opacity=60); 

具有可见性的对象:隐藏仍然有形状,他们只是不可见。 不透明零元素仍然可以被点击并对其他事件做出反应。

我并不完全确定这一点,但我认为屏幕阅读者不会阅读隐藏隐藏的东西,但是他们可以阅读任何东西,而不pipe他们的不透明度。

这是我能想到的唯一区别。

在创build影响元素的用户样式时,我注意到如果将某些元素设置为visibility: hidden ,则input插入符号不会真正与其进行交互。 如果你有

 <div contenteditable><span style='visibility: hidden;'></span></div> 

…那么看起来如果你关注这个div / span,你实际上不能input它。 而不opacity: 0看来你可以。 我没有广泛地testing过这个,但是在这里,没有人讨论过文本input的效果,所以认为这里值得一提。 这似乎可能与上面提到的事件有关。

菲尔说的是真的。

虽然IE支持不透明:

 filter:alpha(opacity=0); 

这些属性具有不同的语义含义。 尽pipe语义CSS听起来可能很愚蠢,但正如其他用户所提到的那样,它对屏幕阅读器等设备有影响 – 语义影响页面的可访问性。

使用按位或0来放置一个数字

我的同事偶然发现了一种使用按位或者:

var a = 13.6 | 0; //a == 13 

我们正在谈论这个问题,想知道几件事情。

  • 它是如何工作的? 我们的理论是使用这样的一个操作符把这个数字转换成一个整数,从而去掉小数部分
  • Math.floor相比,它有什么优势吗? 也许这快一点? (双关不打算)
  • 它有什么缺点吗? 也许这在某些情况下不起作用? 明确是一个明显的问题,因为我们必须弄清楚,好吧,我正在写这个问题。

谢谢。

它是如何工作的? 我们的理论是使用这样的一个操作符把这个数字转换成一个整数,从而去掉小数部分

所有按位运算,除了无符号右移, >>> ,都使用有符号的32位整数。 所以使用按位操作将浮点数转换为整数。

与Math.floor相比,它有什么优势吗? 也许这快一点? (双关不打算)

http://jsperf.com/or-vs-floor/2似乎稍快;

它有什么缺点吗? 也许这在某些情况下不起作用? 明确是一个明显的问题,因为我们必须弄清楚,好吧,我正在写这个问题。

  • 不会通过jsLint。
  • 只有32位有符号整数
  • Odd比较行为: Math.floor(NaN) === NaN ,而(NaN | 0) === 0

这是截断而不是地板。 霍华德的回答是正确的; 但是我想补充一点, Math.floor完全按照负数表示。 在数学上,这是一个地板。

在上面所描述的情况下,程序员更感兴趣的是截断或者完全关闭十进制。 虽然,他们使用的语法掩盖了他们将float转换为int的事实。

你的第一点是正确的。 该数字被转换为一个整数,因此任何十进制数字被删除。 请注意, Math.floor四舍五入到负无穷大的下一个整数,因此在应用到负数时会得到不同的结果。

在ECMAScript 6中,相当于|0是Math.trunc ,我应该说:

通过删除小数位来返回数字的整数部分。 它只是截断点和它后面的数字,无论参数是正数还是负数。

 Math.trunc(13.37) // 13 Math.trunc(42.84) // 42 Math.trunc(0.123) // 0 Math.trunc(-0.123) // -0 Math.trunc("-1.123")// -1 Math.trunc(NaN) // NaN Math.trunc("foo") // NaN Math.trunc() // NaN 
  • 规范说,它被转换为一个整数:

    让lnum ToInt32(lval)。

  • 性能:这已经在jsperf之前测试过了。

Interesting Posts

睡眠()后面的algorithm是什么?

python的time.sleep()有多准确?

等待和睡眠之间的区别

JavaScript中是否有睡眠/暂停/等待function?

Java的Thread.sleep何时抛出InterruptedException?

在Windows上为Java准确hibernate

什么是sleep()的JavaScript版本?

如何保持.NET控制台应用程序运行?

为什么Thread.Sleep如此有害

如何在JavaScript循环中添加延迟?

Thread.Sleep(TimeSpan)有多准确?

如何在Windows的命令提示符下睡5秒钟? (或DOS)

如何在Windows上使线程睡眠时间less于一毫秒

为什么睡眠(500)的成本超过500毫秒?

在Objective-C / Cocoa中Java的Thread.sleep()相当于什么?

睡眠()后面的algorithm是什么?

如何在Swing中创build延迟

如何获得一个UNIX脚本每15秒运行一次?

Timer和TimerTask与Java中的Thread + sleep

睡眠JavaScript – 行动之间的延迟

Bash:无限的睡眠(无限的阻挡)

睡眠时间是否计算执行时间限制?

如何保持.NET控制台应用程序运行?

比较使用Thread.Sleep和Timer来延迟执行

NetBeans / Java /新提示:在循环中调用Thread.sleep

如何在Swing中创build延迟

python的time.sleep()有多准确?

如何“睡眠”,直到在.NET 4.0中请求超时或取消

为什么睡眠(500)的成本超过500毫秒?

如何获得一个UNIX脚本每15秒运行一次?

time.sleep – 睡觉线程或进程?

睡眠时间是否计算执行时间限制?

什么是sleep()的JavaScript版本?

Bash:无限的睡眠(无限的阻挡)

Thread.sleep与TimeUnit.SECONDS.sleep

睡眠()后面的algorithm是什么?

如何使用Qt创build暂停/等待function?

在Objective-C / Cocoa中Java的Thread.sleep()相当于什么?

JavaScript睡眠/等待继续之前

如何获得一个UNIX脚本每15秒运行一次?

如何“睡眠”,直到在.NET 4.0中请求超时或取消

睡眠JavaScript – 行动之间的延迟

Thread.sleep与TimeUnit.SECONDS.sleep

Java的Thread.sleep何时抛出InterruptedException?

如何在JavaScript循环中添加延迟?

在Objective-C / Cocoa中Java的Thread.sleep()相当于什么?

在Windows上为Java准确hibernate

为什么睡眠(500)的成本超过500毫秒?

Timer和TimerTask与Java中的Thread + sleep

如何在Windows的命令提示符下睡5秒钟? (或DOS)

睡眠时间是否计算执行时间限制?

如何在JavaScript循环中添加延迟?

什么是_GLIBCXX_USE_NANOSLEEP?

Java的Thread.sleep何时抛出InterruptedException?

我如何在Perl中睡一毫秒?

Python time.sleep

在Objective-C / Cocoa中Java的Thread.sleep()相当于什么?

在VBA中是否有等价于Thread.Sleep()?

睡眠()后面的algorithm是什么?

如何在Swing中创build延迟

Java:Thread.currentThread()。sleep(x)与Thread.sleep(x)

是否有一个替代睡眠函数在C到毫秒?

睡眠时间是否计算执行时间限制?

Timer和TimerTask与Java中的Thread + sleep

如何“睡眠”,直到在.NET 4.0中请求超时或取消

比较使用Thread.Sleep和Timer来延迟执行

睡眠JavaScript – 行动之间的延迟

如何获得一个UNIX脚本每15秒运行一次?

JavaScript睡眠/等待继续之前

我如何在Perl中睡一毫秒?

python的time.sleep()有多准确?

如何“睡眠”,直到在.NET 4.0中请求超时或取消

如何在JavaScript循环中添加延迟?

如何保持.NET控制台应用程序运行?

为什么睡眠(500)的成本超过500毫秒?

time.sleep – 睡觉线程或进程?

我如何在Perl中睡一毫秒?

为什么Thread.Sleep如此有害

是否有一个替代睡眠函数在C到毫秒?

Thread.Sleep(TimeSpan)有多准确?

Thread.Sleep(TimeSpan)有多准确?

为什么睡眠(500)的成本超过500毫秒?

睡眠JavaScript – 行动之间的延迟

JavaScript睡眠/等待继续之前

Python time.sleep

如何使用Qt创build暂停/等待function?

如何“睡眠”,直到在.NET 4.0中请求超时或取消

睡眠时间是否计算执行时间限制?

如何获得一个UNIX脚本每15秒运行一次?

如何保持.NET控制台应用程序运行?

我如何让我的Python程序睡眠50毫秒?

任何桌面浏览器都可以检测计算机何时从睡眠中恢复?

NetBeans / Java /新提示:在循环中调用Thread.sleep

睡眠()后面的algorithm是什么?

在Windows上为Java准确hibernate

Bash:无限的睡眠(无限的阻挡)

睡眠时间是否计算执行时间限制?

wait()和sleep()之间的区别

我如何在Perl中睡一毫秒?

如何保持.NET控制台应用程序运行?

睡眠()后面的algorithm是什么?

Python time.sleep

什么是_GLIBCXX_USE_NANOSLEEP?

为什么Thread.Sleep如此有害

什么是sleep()的JavaScript版本?

Bash:无限的睡眠(无限的阻挡)

等待和睡眠之间的区别

time.sleep – 睡觉线程或进程?

我如何在Perl中睡一毫秒?

比较使用Thread.Sleep和Timer来延迟执行

Java:Thread.currentThread()。sleep(x)与Thread.sleep(x)

睡眠时间是否计算执行时间限制?

如何在Windows的命令提示符下睡5秒钟? (或DOS)

如何获得一个UNIX脚本每15秒运行一次?

什么是sleep()的JavaScript版本?

JavaScript睡眠/等待继续之前

Bash:无限的睡眠(无限的阻挡)

比较使用Thread.Sleep和Timer来延迟执行

为什么Thread.Sleep如此有害

Thread.Sleep(TimeSpan)有多准确?

如何“睡眠”,直到在.NET 4.0中请求超时或取消

Bash:无限的睡眠(无限的阻挡)

Thread.sleep与TimeUnit.SECONDS.sleep

如何使用Qt创build暂停/等待function?

是否有一个替代睡眠函数在C到毫秒?

睡眠时间是否计算执行时间限制?

Java的Thread.sleep何时抛出InterruptedException?

在VBA中是否有等价于Thread.Sleep()?

睡了几毫秒

为什么Thread.Sleep如此有害

在Objective-C / Cocoa中Java的Thread.sleep()相当于什么?

wait()和sleep()之间的区别

在Windows上为Java准确hibernate

如何在Windows上使线程睡眠时间less于一毫秒

睡眠()后面的algorithm是什么?

NetBeans / Java /新提示:在循环中调用Thread.sleep

比较使用Thread.Sleep和Timer来延迟执行

为什么睡眠(500)的成本超过500毫秒?

如何在JavaScript循环中添加延迟?

如何“睡眠”,直到在.NET 4.0中请求超时或取消

time.sleep – 睡觉线程或进程?

我如何在Perl中睡一毫秒?

NetBeans / Java /新提示:在循环中调用Thread.sleep

Java:Thread.currentThread()。sleep(x)与Thread.sleep(x)

在Windows上为Java准确hibernate

在VBA中是否有等价于Thread.Sleep()?

任何桌面浏览器都可以检测计算机何时从睡眠中恢复?

Java的Thread.sleep何时抛出InterruptedException?

睡眠()后面的algorithm是什么?

如何“睡眠”,直到在.NET 4.0中请求超时或取消

如何在Windows上使线程睡眠时间less于一毫秒

为什么Thread.Sleep如此有害

如何在JavaScript循环中添加延迟?

如何获得一个UNIX脚本每15秒运行一次?

time.sleep – 睡觉线程或进程?

为什么睡眠(500)的成本超过500毫秒?

Java:Thread.currentThread()。sleep(x)与Thread.sleep(x)

JavaScript中是否有睡眠/暂停/等待function?

如何“睡眠”,直到在.NET 4.0中请求超时或取消

如何使用Qt创build暂停/等待function?

Timer和TimerTask与Java中的Thread + sleep

在Windows上为Java准确hibernate

是否有一个替代睡眠函数在C到毫秒?

JavaScript睡眠/等待继续之前

任何桌面浏览器都可以检测计算机何时从睡眠中恢复?

Thread.Sleep(TimeSpan)有多准确?

time.sleep – 睡觉线程或进程?

睡了几毫秒

wait()和sleep()之间的区别

为什么睡眠(500)的成本超过500毫秒?

如何在Windows的命令提示符下睡5秒钟? (或DOS)

如何“睡眠”,直到在.NET 4.0中请求超时或取消

比较使用Thread.Sleep和Timer来延迟执行

如何在Windows上使线程睡眠时间less于一毫秒

Thread.sleep与TimeUnit.SECONDS.sleep

等待和睡眠之间的区别

睡了几毫秒

在Windows上为Java准确hibernate

Python time.sleep

是否有一个替代睡眠函数在C到毫秒?

为什么睡眠(500)的成本超过500毫秒?

JavaScript中是否有睡眠/暂停/等待function?

等待和睡眠之间的区别

是否有一个替代睡眠函数在C到毫秒?

如何在Windows的命令提示符下睡5秒钟? (或DOS)

睡眠时间是否计算执行时间限制?

如何获得一个UNIX脚本每15秒运行一次?

睡了几毫秒

JavaScript睡眠/等待继续之前

Thread.Sleep(TimeSpan)有多准确?

wait()和sleep()之间的区别

什么是_GLIBCXX_USE_NANOSLEEP?

Thread.Sleep(TimeSpan)有多准确?

如何“睡眠”,直到在.NET 4.0中请求超时或取消

Thread.sleep与TimeUnit.SECONDS.sleep

为什么睡眠(500)的成本超过500毫秒?

time.sleep – 睡觉线程或进程?

Java:Thread.currentThread()。sleep(x)与Thread.sleep(x)

如何使用Qt创build暂停/等待function?

等待和睡眠之间的区别

比较使用Thread.Sleep和Timer来延迟执行

是否有一个替代睡眠函数在C到毫秒?

time.sleep – 睡觉线程或进程?

为什么Thread.Sleep如此有害

在Windows上为Java准确hibernate

为什么睡眠(500)的成本超过500毫秒?

如何在Swing中创build延迟

在VBA中是否有等价于Thread.Sleep()?

睡了几毫秒

如何“睡眠”,直到在.NET 4.0中请求超时或取消

Thread.sleep与TimeUnit.SECONDS.sleep

Bash:无限的睡眠(无限的阻挡)

如何在Windows的命令提示符下睡5秒钟? (或DOS)

NetBeans / Java /新提示:在循环中调用Thread.sleep

JavaScript中是否有睡眠/暂停/等待function?

如何使用Qt创build暂停/等待function?

如何在Swing中创build延迟

Java的Thread.sleep何时抛出InterruptedException?

睡眠JavaScript – 行动之间的延迟

比较使用Thread.Sleep和Timer来延迟执行

当使用Thread.sleep(x)或wait()时,我得到exception

等待和睡眠之间的区别

Python time.sleep

在VBA中是否有等价于Thread.Sleep()?

我如何让我的Python程序睡眠50毫秒?

如何在Windows上使线程睡眠时间less于一毫秒

什么是_GLIBCXX_USE_NANOSLEEP?

我如何在Perl中睡一毫秒?

任何桌面浏览器都可以检测计算机何时从睡眠中恢复?

在Objective-C / Cocoa中Java的Thread.sleep()相当于什么?

如何使用Qt创build暂停/等待function?

睡眠时间是否计算执行时间限制?

JavaScript睡眠/等待继续之前

如何获得一个UNIX脚本每15秒运行一次?

如何“睡眠”,直到在.NET 4.0中请求超时或取消

睡眠JavaScript – 行动之间的延迟

wait()和sleep()之间的区别

睡眠()后面的algorithm是什么?

在Windows上为Java准确hibernate

Thread.Sleep(TimeSpan)有多准确?