Dart/Flutter如何检查一个值是否为整数?

23

如何检查一个值是整数还是包含小数?在Javascript中,我们有isInteger,但我在Dart中找不到等价的方法。

我们似乎有isEvenisOddisFiniteisInfiniteisNaNisNegative的检查方法,但没有isInteger


仍然没有在Flutter中实际可行的有效答案。 - Hasen
6个回答

44
Dart的数字(类型num)可以是整数(类型int)或浮点数(类型double)。
要检查一个数字是否为int很容易,只需执行value is int
稍微困难一些的任务是检查double值是否具有整数值,即没有小数部分。没有简单的函数可以回答这个问题,但可以执行value == value.roundToDouble()。这将从double值中去除任何小数部分,并将其与原始值进行比较。如果它们相同,则表示没有小数部分。
因此,一个辅助函数可以是:
bool isInteger(num value) => 
    value is int || value == value.roundToDouble();

我使用roundToDouble()而不是只用round(),因为后者会将值转换为整数,这可能会导致大的双精度值得到一个不同的值。
另一个测试一个具有整数值的double的方法可以是value % 1.0 == 0.0,但这种写法不够易读,也不太可能更高效,尽管它确实有效,但在我能够信任它之前,我必须检查% 1.0对于double.infinity的结果(它会返回NaN)。

3
这实际上是有效的,不像其他答案。尽管我认为这应该是Dart的一部分。因为它有一些不太有用的函数,比如isOdd,isEven等,这些函数甚至更容易检查。 - Hasen
我很惊讶地发现似乎没有与C语言的modf等效的函数来提取double类型数的整数和小数部分。 - jamesdlin
不应该关心您使用哪个函数 truncateToDoubleroundToDoublefloorToDoubleceilToDouble,除了性能。似乎在 VM 上,roundToDouble 比其他三个函数慢,当编译成 JS 并在 Chrome 上运行时,roundToDoubletruncateToDouble 都会变得更慢。除非我知道这是我的应用程序的瓶颈(然后我也会检查其他浏览器),否则它们都不会受到太大影响。 - lrn
请注意,1 is int 在 Native 和 Web 上都可以工作。但是,在 Native 上,1 is double 实际上会返回 false,而在 Web 上会返回 true!而且,1.0 is int 在 Web 上会返回 true!看起来 Dart 的制造者真的不希望你使用这个习惯用法,因为他们不能保证所有平台的结果匹配。我建议不要使用它,因为它可能会在未来发生变化。https://dart.dev/guides/language/numbers - esotericpig
1
如果目标是检测非分数num值(这里就是这样),那么is int是正确的,在Web上,它就是你所需要的(好吧,如果你包括无限值,否则你可能需要添加&& x.isFInite)。上面的代码适用于当前的Dart数字实现,如果有任何变化,很可能是Web获得了真正的整数(作为JS的一个特性或通过编译为WASM而不是JS),然后它仍然是正确的。 确实,您不应该使用is int来推断该值不是double - lrn
显示剩余2条评论

21

使用取模运算符 %:

  bool isInteger(num value) => (value % 1) == 0;

与扩展方法相同:

  extension NumExtensions on num {
    bool get isInt => (this % 1) == 0;
  }

使用方法:

  double d = 2.6;
  double d2 = 2.0;
  int i = 2;
  print(d.isInt); // returns false
  print(d2.isInt); // returns true
  print(i.isInt); // returns true

1
我不确定这种方法的速度如何与其他方法相比,但我觉得使用取模运算符很容易理解。我认为这取决于个人喜好。然而,我建议避免在本地对象上使用扩展方法,因为扩展方法可能会导致更多的混淆,并且难以确定其来源。我建议创建一个名为Math的辅助类来处理数字。 - Rob

6
void main() {
  int a = 10;
  print(a is int); // Prints true
}

或者

void main() {
  dynamic a = 10;
  print(a is int ? a/10 :"Not an int"); // Prints 1
}

实际上它似乎不起作用?print((2 + 2) is int); = true,print((2 / 2) is int); = false ?? - Hasen
print((2 / 2) is int); and print((2 + 2) is int); both prints true - Sharad Paghadal
我在Flutter中没有得到这个,那是哪个版本的Dart?你是在Flutter中检查它吗? - Hasen
我认为您应该删除您的答案,因为已经确认它在Dart中无法工作。它不能验证整数,所以对于其他人看到您的答案是误导性的。它在Dartpad上可以工作,因为Dartpad编译成JavaScript,但在实际的Dart代码中,例如我们在Flutter中看到的那样,它无法工作。 - Hasen

2
我是这样做的,而且工作得很好:

bool _isInteger(double value) => value == value.toInt();

方法 toInt() 会去掉小数部分,所以如果去掉后没有改变,就代表它是一个整数。

0

要检查Dart中任何变量的数据类型,您可以使用关键字is。例如:

void main() {
     int x = 10;
     double y = 20;
     checkType(x, y);
    }

void checkType(dynamic x, dynamic y) {
  if (x is int) {
    print(x);
  } else {
    print(y);
  }
}

上面的代码将打印出10,因为主函数内部的变量x是一个整数数据类型。

0

我刚刚创建了两个扩展方法(在DART中), 如果给定的数字是整数(整数),则返回true,如果给定的数字是双精度(小数),则返回false。

这里 isInteger 方法将提供布尔值,而 getDoubleOrInt 方法将提供字符串值,该值为整数或两位小数精确的十进制字符串格式值。

扩展方法

extension OnNumber on num {
  String get getDoubleOrInt {
    if (toString().split('.').length > 1) {
      if (int.parse(toString().split('.').elementAt(1)) > 0) {
        return toDouble().toStringAsFixed(2);
      } else {
        return toInt().toString();
      }
    } else {
      return toInt().toString();
    }
  }

  bool get isInteger {
    if (toString().split('.').length > 1) {
      if (int.parse(toString().split('.').elementAt(1)) > 0) {
        return false;
      } else {
        return true;
      }
    } else {
      return true;
    }
  }
}

应用示例

void main() {
  double x = 3.5999;
  
  print(x.isInteger); // false
  print(x.getDoubleOrInt); // 3.60
  
  int y = 123; 
  
  print(y.isInteger);  // true
  print(y.getDoubleOrInt); // 123
  
}


希望你喜欢这两种方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接