3

How do you negate a bitwise complement of a Double in Swift 4?

In particular, I'm trying to convert the following (trvial) javascript line to Swift:

var j = -~(0.707 * x);

Using it as is gives the error message "Unary operators may not be juxtaposed; parenthesize inner expression".

Ok, I don't like that either. So, I tried:

var j = -(~(0.707 * x))  //Compile error: "Unary operator '~' cannot be applied to an operand of type 'Double'".

Then:

var j = -(~((0.707 * x).bitPattern))  //Compile error: "Unary operator '-' cannot be applied to an operand of type 'UInt64'".

And then:

var j = -Int64(~((0.707 * x).bitPattern)))

which compiles but crashes with "Fatal error: Not enough bits to represent a signed value"

Eventually, I found myself standing on my head rubbing my belly and sticking pins in a doll bought in Louisiana while sacrificing a frozen chicken.

Greg
  • 667
  • 8
  • 19

2 Answers2

3

JavaScript implicitly truncates a number to the next integral value towards zero before applying the bitwise-not operator ~:

console.log(-~(12.34))    // 13
console.log(-~(-12.34))   // -11

Therefore

var j = -~(0.707 * x); 

would be in Swift

let j = -(~Int(0.707 * x))

or, since negative integers in Swift use a two's complement representation, simply

let j = Int(0.707 * x) + 1

Examples:

print(-(~Int(12.34)))   // 13
print(Int(12.34) + 1)   // 13

print(-(~Int(-12.34)))  // -11
print(Int(-12.34) + 1)  // -11
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • I always prefer understanding what's going on, but I have to admit, I was confused by the javascript line. So, if I'm not mistaken, for positive x all it does is round up then truncate? – Greg Dec 13 '17 at 16:07
  • @Greg: Almost. It truncates down (towards zero) and then adds 1. For example, for all numbers 5.0, 5.1, 5.99 the result is 6 (truncated to 5, then +1). For all numbers -4.0, -4.1, -4.99 the result is -3 (truncated to -4, then +1) – Martin R Dec 13 '17 at 16:10
  • Yes, I misstated that. Very interesting! Why would that javascript line not be written like your 2nd print line above? Is it significantly faster? – Greg Dec 13 '17 at 16:40
  • @Greg: Using `~` seems to be a method to truncate a double which is faster than `Math.floor()` (https://stackoverflow.com/q/5971645/1187415). I am not an JavaScript expert, so I cannot judge if that is "good" or not. – If you provide more information (where does that code come from and what is it used for?) then we might figure out how to do the same properly in Swift. – Martin R Dec 13 '17 at 18:17
  • Thank you, Martin. No big deal, I was just curious. I always try to optimize things too, but I'm not going to bother with this since it will only run once in a while. Thank you very much for the help and clarifications! – Greg Dec 14 '17 at 02:12
1

I guess is not that much complicated:

Swift:

var result = -Double(bitPattern:~(0.707 * 10.0).bitPattern) // replace 10.0 with x

Javascript:

var j = -~(0.707 * x);

I think the most important is the "casting back" from bitPattern to Double, if you miss that part you may have not only compilation problems but also semantic problems; you may guess you are operating with base 10 numbers, instead you have a mix of base 10 and base 2


edit:

as Martin said, JS implicitly truncates, so although the above results won't match, I think the Swift solution with bitPattern is the most correct

mugx
  • 9,869
  • 3
  • 43
  • 55