Multiplying 2 values gives the original value but dividing the same values gives the right answer

47 Views Asked by At

I have 2 values that I can not get to multiply together and get the right answer. Here is my very simple code:

$data | ForEach-Object {
            $newMHV = ($_.'North' * $_.'Measured Heat Value') 
            $_.'North BTU' = $newMHV
            $_               # Output the modified row
            } | Export-Csv $AFw -NoTypeInformation

The first time through the loop $_.'North' = 1648 and $_.'Measured Heat Value' = 1.022 $newMHV should be 1684.xxx. $newMVH always shows 1648 on the first value then changes to the second value.

When I change the calculation to division, I get the correct value.

I have tried trimming the values, etc. but I cant find it. I may need to convert them to a numeric but why would it work when I divide the values?

Note: $data is a .csv file that I have imported.

1

There are 1 best solutions below

1
mklement0 On BEST ANSWER

The crucial pointer is in the comments:

  • Data imported from a CSV file is invariably [string]-typed.

  • Thus, you must ensure that (at least) your LHS operand is of type [double] (or another suitable numeric type) to make your calculation work as expected (PowerShell will coerce the RHS to [double] too, as needed):

$newMHV = [double] $_.'North' * $_.'Measured Heat Value'

As for what you tried:

  • The * operator also operates on strings: if the LHS is a [string] and the RHS is / can be coerced to a number, the string is "multiplied" (duplicated) by the RHS number; that is, if the number is $n, you get the concatenation of $n copies of the LHS string;[1] e.g.:

    # -> 'abcabc'
    'abc' * 2 
    
    • In your case, the RHS, '1.022' didn't represent an integer, which means that PowerShell implicitly did the following: [int] '1.022' - which yields 1; therefore, your "calculation" was ultimately the equivalent of the following, which amounted to a virtual no-op:

      '1648' * 1 # -> '1648'
      
  • By contrast, the / operator operates only on numbers, so it coerces even [string]-typed operands to a number (which may situationally be an integer data type such as [int] or [double], as needed).

    # -> a [double] with value 2.5 - even though both operands are *strings*
    '10' / '4' 
    

[1] It follows that if $n is 1, you get (an identical copy of) the string itself, and if it is 0, you get the empty string ('').