在Javascript中将double转换为int而不进行舍入

时间:2011-12-05 16:27:26

标签: javascript casting floating-point int

在C#中,以下代码返回2:

double d = 2.9;
int i = (int)d;
Debug.WriteLine(i);

然而,在Javascript中,将我所知道的“double”转换为“int”的唯一方法是使用Math.round / floor / toFixed等。有没有办法转换为int in in没有四舍五入的Javascript?我知道Number()的性能影响,所以我宁愿避免在可能的情况下将其转换为字符串。

8 个答案:

答案 0 :(得分:123)

使用parseInt()

var num = 2.9
console.log(parseInt(num, 10)); // 2

您也可以使用|

var num = 2.9
console.log(num | 0); // 2

答案 1 :(得分:48)

我发现“parseInt”建议非常好奇,因为“parseInt”在设计上对字符串进行操作。这就是为什么它的名字里面有“解析”这个词。

完全避免函数调用的技巧是

var truncated = ~~number;

“〜”一元运算符的双重应用将为您提供双精度值的截断版本。但是,该值限制为32位精度,与所有其他JavaScript操作一样,隐含地将数字视为整数(如数组索引和按位运算符)。

编辑 - 在很长一段时间后的更新中,~~技巧的另一种替代方法是将值与零按位OR运算:

var truncated = number|0;

答案 2 :(得分:7)

只需使用parseInt()并确保包含基数,以便获得可预测的结果:

parseInt(d, 10);

答案 3 :(得分:5)

Javascript中没有int这样的东西。所有Numbers实际上都是幕后的双倍*因此您不能依赖类型系统为您发出舍入顺序,就像在C或C#中一样。

你不需要担心精度问题(因为双精确到正确表示任何最大为2 ^ 53的整数)但你真的很难使用Math.floor(或其他等效的技巧),如果你想要舍入到最近的整数。


*大多数JS引擎都可以使用本机int,但所有JS编号都必须具有双重语义。

答案 4 :(得分:1)

类似于使用标准lib将C#强制转换为(int)

Math.trunc(1.6) // 1
Math.trunc(-1.6) // -1

答案 5 :(得分:1)

截断技巧可以完全避免调用函数

var number = 2.9
var truncated = number - number % 1;
console.log(truncated); // 2 

要将浮点数四舍五入为最接近的整数,请使用addition/subtraction技巧。这适用于绝对值<2 ^ 51的数字。

var number = 2.9
var rounded = number + 6755399441055744.0 - 6755399441055744.0;  // (2^52 + 2^51)
console.log(rounded); // 3 

注意:

使用"round half to even"作为平局规则,中途值四舍五入到最接近的值。因此,例如+23.5变为+ 24,+ 24.5也变为+24。四舍五入取整模式的这种变体也称为银行家取整

幻数6755399441055744.0在stackoverflow帖子"A fast method to round a double to a 32-bit int explained"中进行了解释。

// Round to whole integers using arithmetic operators
let trunc = (v) => v - v % 1;
let ceil  = (v) => trunc(v % 1 > 0 ? v + 1 : v);
let floor = (v) => trunc(v % 1 < 0 ? v - 1 : v);
let round = (v) => trunc(v < 0 ? v - 0.5 : v + 0.5);

let roundHalfEven = (v) => v + 6755399441055744.0 - 6755399441055744.0; // (2^52 + 2^51)

console.log("number  floor   ceil  round  trunc");
var array = [1.5, 1.4, 1.0, -1.0, -1.4, -1.5];
array.forEach(x => {
    let f = x => (x).toString().padStart(6," ");
    console.log(`${f(x)} ${f(floor(x))} ${f(ceil(x))} ${f(round(x))} ${f(trunc(x))}`);  
});

答案 6 :(得分:0)

正如@Quentin和@Pointy在其注释中指出的那样,使用parseInt()并不是一个好主意,因为它旨在将字符串转换为整数。当您将十进制数字传递给它时,它首先将数字转换为字符串,然后将其转换为整数。我建议您根据需要使用Math.trunc()Math.floor()~~num~~vnum | 0num << 0num >> 0This performance test展示了parseInt()Math.floor()的性能差异。 另外,this post解释了所建议方法之间的区别。

答案 7 :(得分:0)

这个怎么样:

if (stringToSearch.IndexOfAny( ".,;:?!".ToCharArray() ) == -1) { ... }