【问题标题】:How to convert imperial units of length into metric?如何将英制长度单位转换为公制?
【发布时间】:2010-09-24 10:01:39
【问题描述】:

在这里,我面临一个我相信(或至少希望)已经解决了 100 万次的问题。 我作为输入得到的是一个字符串,它以英制单位表示对象的长度。它可以是这样的:

$length = "3' 2 1/2\"";

或者像这样:

$length = "1/2\"";

或者实际上以我们通常会写的任何其他方式。

为了减少全球车轮发明,我想知道是否有一些函数、类或正则表达式可以让我将英制长度转换为公制长度?

【问题讨论】:

  • 与奥巴马交谈,现在是改变公制的时候了。如果美国这样做,英国可能会加入......
  • 下次见到他时我一定会提到...

标签: php regex code-snippets


【解决方案1】:

也许看看units library?不过,它似乎没有 PHP 绑定。

【讨论】:

    【解决方案2】:

    正则表达式看起来像这样:

    "([0-9]+)'\s*([0-9]+)\""
    

    (其中 \s 代表空格 - 我不确定它在 php 中是如何工作的)。然后你提取第一+第二组并做

    (int(grp1)*12+int(grp2))*2.54
    

    转换为厘米。

    【讨论】:

      【解决方案3】:

      这是我的解决方案。它使用eval() 来评估表达式,但不用担心,最后的正则表达式检查使其完全安全。

      function imperial2metric($number) {
          // Get rid of whitespace on both ends of the string.
          $number = trim($number);
      
          // This results in the number of feet getting multiplied by 12 when eval'd
          // which converts them to inches.
          $number = str_replace("'", '*12', $number);
      
          // We don't need the double quote.
          $number = str_replace('"', '', $number);
      
          // Convert other whitespace into a plus sign.
          $number = preg_replace('/\s+/', '+', $number);
      
          // Make sure they aren't making us eval() evil PHP code.
          if (preg_match('/[^0-9\/\.\+\*\-]/', $number)) {
              return false;
          } else {
              // Evaluate the expression we've built to get the number of inches.
              $inches = eval("return ($number);");
      
              // This is how you convert inches to meters according to Google calculator.
              $meters = $inches * 0.0254;
      
              // Returns it in meters. You may then convert to centimeters by
              // multiplying by 100, kilometers by dividing by 1000, etc.
              return $meters;
          }
      }
      

      例如,字符串

      3' 2 1/2"
      

      转换为表达式

      3*12+2+1/2
      

      被评估为

      38.5
      

      最终转换为 0.9779 米。

      【讨论】:

      • “3 英尺 2.5 英寸”怎么样? :D 码呢?链子、杆子、栖木、杆子等有点深奥,但弗隆用于赛马(以及每两周神话般的弗隆)。
      • Jeremy 非常酷的解决方案。我会用偷来荣耀你! Jonathan 对于“3 ft 2.5 in”,您只需要一对额外的正则表达式即可将“ft”转换为“*12”并将“in”转换为“”。
      • ehh.... 这实在是太过分了。正则表达式分组解决方案有 2 行长,并且不评估任何内容,因为 php 必须解析表达式,形成 AST,然后评估它,所以效率低得多。 -1
      • @Claudiu:您的正则表达式不处理像“1/2”这样的分数或像“1 1/2”这样的混合分数。
      • @jeremy - 啊,真的,我没看到这个。如果给出了这些,那么是的,这种方式更好。
      【解决方案4】:

      Zend 框架有一个用于此目的的测量组件。我建议你检查一下 - here

      $unit = new Zend_Measure_Length($length,Zend_Measure_Length::YARD);
      $unit -> convertTo(Zend_Measure_Length::METER);
      

      【讨论】:

      • 哇!不错的组件...虽然缺少文档,但我肯定会检查一下!
      【解决方案5】:

      英制字符串值有点复杂,所以我使用了以下表达式:

      string pattern = "(([0-9]+)')*\\s*-*\\s*(([0-9])*\\s*([0-9]/[0-9])*\")*";
      Regex regex = new Regex( pattern );
      Match match = regex.Match(sourceValue);
      if( match.Success ) 
      {
          int feet = 0;
          int.TryParse(match.Groups[2].Value, out feet);
          int inch = 0;
          int.TryParse(match.Groups[4].Value, out inch);
          double fracturalInch = 0.0;
          if (match.Groups[5].Value.Length == 3)
               fracturalInch = (double)(match.Groups[5].Value[0] - '0') / (double)(match.Groups[5].Value[2] - '0');
      
          resultValue = (feet * 12) + inch + fracturalInch;
      

      【讨论】:

      • 进一步解释您的答案可能会更有帮助。
      猜你喜欢
      • 2020-01-30
      • 1970-01-01
      • 2019-03-20
      • 1970-01-01
      • 1970-01-01
      • 2017-04-18
      • 1970-01-01
      • 1970-01-01
      • 2017-02-10
      相关资源
      最近更新 更多