(Not 1) evaluates to -2 for some reason2019 Community Moderator ElectionVBA F9 Button recognized left mouse button not recognizedWhat are bitwise shift (bit-shift) operators and how do they work?Which equals operator (== vs ===) should be used in JavaScript comparisons?Does Python have a ternary conditional operator?What is the !! (not not) operator in JavaScript?Behaviour of increment and decrement operators in PythonReference — What does this symbol mean in PHP?What are the basic rules and idioms for operator overloading?What's the difference between equal?, eql?, ===, and ==?What does the C ??!??! operator do?Why don't Java's +=, -=, *=, /= compound assignment operators require casting?
How are passwords stolen from companies if they only store hashes?
My friend is being a hypocrite
What is the significance behind "40 days" that often appears in the Bible?
Brake pads destroying wheels
How do hiring committees for research positions view getting "scooped"?
If "dar" means "to give", what does "daros" mean?
What does Deadpool mean by "left the house in that shirt"?
I got the following comment from a reputed math journal. What does it mean?
HP P840 HDD RAID 5 many strange drive failures
How does 取材で訪れた integrate into this sentence?
Am I eligible for the Eurail Youth pass? I am 27.5 years old
How can an organ that provides biological immortality be unable to regenerate?
Can a medieval gyroplane be built?
When to use snap-off blade knife and when to use trapezoid blade knife?
Maths symbols and unicode-math input inside siunitx commands
In what cases must I use 了 and in what cases not?
I seem to dance, I am not a dancer. Who am I?
Hausdorff dimension of the boundary of fibres of Lipschitz maps
Have the tides ever turned twice on any open problem?
What are substitutions for coconut in curry?
Would it be believable to defy demographics in a story?
Violin - Can double stops be played when the strings are not next to each other?
Recruiter wants very extensive technical details about all of my previous work
Help rendering a complicated sum/product formula
(Not 1) evaluates to -2 for some reason
2019 Community Moderator ElectionVBA F9 Button recognized left mouse button not recognizedWhat are bitwise shift (bit-shift) operators and how do they work?Which equals operator (== vs ===) should be used in JavaScript comparisons?Does Python have a ternary conditional operator?What is the !! (not not) operator in JavaScript?Behaviour of increment and decrement operators in PythonReference — What does this symbol mean in PHP?What are the basic rules and idioms for operator overloading?What's the difference between equal?, eql?, ===, and ==?What does the C ??!??! operator do?Why don't Java's +=, -=, *=, /= compound assignment operators require casting?
Why does (Not 1) evaluate as -2? I would expect it to evaluate as 0.
vba operators bitwise-operators bitwise-not
add a comment |
Why does (Not 1) evaluate as -2? I would expect it to evaluate as 0.
vba operators bitwise-operators bitwise-not
1
Two's complement? In (8-bit) binary, 1 is00000001
and -2 is11111110
, you're doing a bitwise not.
– jonrsharpe
Mar 7 at 17:16
So how do I stop doing a bitwise not? InStr returns a position in a string and I need to take action if a string is not found, ie If Not InStr....
– public wireless
Mar 7 at 17:23
Well what value do you get if it's not found? Check for that.
– jonrsharpe
Mar 7 at 17:24
InStr returns some index greater than 0 if found, and applying Not makes the value -2. Thus because the value is -2 and not 0, my if statement doesn't work
– public wireless
Mar 7 at 17:26
2
And what does it return if not found?! Maybe check docs.microsoft.com/en-us/office/vba/language/reference/…
– jonrsharpe
Mar 7 at 17:27
add a comment |
Why does (Not 1) evaluate as -2? I would expect it to evaluate as 0.
vba operators bitwise-operators bitwise-not
Why does (Not 1) evaluate as -2? I would expect it to evaluate as 0.
vba operators bitwise-operators bitwise-not
vba operators bitwise-operators bitwise-not
edited Mar 7 at 17:36
Mathieu Guindon
44.2k769151
44.2k769151
asked Mar 7 at 17:14
public wirelesspublic wireless
536618
536618
1
Two's complement? In (8-bit) binary, 1 is00000001
and -2 is11111110
, you're doing a bitwise not.
– jonrsharpe
Mar 7 at 17:16
So how do I stop doing a bitwise not? InStr returns a position in a string and I need to take action if a string is not found, ie If Not InStr....
– public wireless
Mar 7 at 17:23
Well what value do you get if it's not found? Check for that.
– jonrsharpe
Mar 7 at 17:24
InStr returns some index greater than 0 if found, and applying Not makes the value -2. Thus because the value is -2 and not 0, my if statement doesn't work
– public wireless
Mar 7 at 17:26
2
And what does it return if not found?! Maybe check docs.microsoft.com/en-us/office/vba/language/reference/…
– jonrsharpe
Mar 7 at 17:27
add a comment |
1
Two's complement? In (8-bit) binary, 1 is00000001
and -2 is11111110
, you're doing a bitwise not.
– jonrsharpe
Mar 7 at 17:16
So how do I stop doing a bitwise not? InStr returns a position in a string and I need to take action if a string is not found, ie If Not InStr....
– public wireless
Mar 7 at 17:23
Well what value do you get if it's not found? Check for that.
– jonrsharpe
Mar 7 at 17:24
InStr returns some index greater than 0 if found, and applying Not makes the value -2. Thus because the value is -2 and not 0, my if statement doesn't work
– public wireless
Mar 7 at 17:26
2
And what does it return if not found?! Maybe check docs.microsoft.com/en-us/office/vba/language/reference/…
– jonrsharpe
Mar 7 at 17:27
1
1
Two's complement? In (8-bit) binary, 1 is
00000001
and -2 is 11111110
, you're doing a bitwise not.– jonrsharpe
Mar 7 at 17:16
Two's complement? In (8-bit) binary, 1 is
00000001
and -2 is 11111110
, you're doing a bitwise not.– jonrsharpe
Mar 7 at 17:16
So how do I stop doing a bitwise not? InStr returns a position in a string and I need to take action if a string is not found, ie If Not InStr....
– public wireless
Mar 7 at 17:23
So how do I stop doing a bitwise not? InStr returns a position in a string and I need to take action if a string is not found, ie If Not InStr....
– public wireless
Mar 7 at 17:23
Well what value do you get if it's not found? Check for that.
– jonrsharpe
Mar 7 at 17:24
Well what value do you get if it's not found? Check for that.
– jonrsharpe
Mar 7 at 17:24
InStr returns some index greater than 0 if found, and applying Not makes the value -2. Thus because the value is -2 and not 0, my if statement doesn't work
– public wireless
Mar 7 at 17:26
InStr returns some index greater than 0 if found, and applying Not makes the value -2. Thus because the value is -2 and not 0, my if statement doesn't work
– public wireless
Mar 7 at 17:26
2
2
And what does it return if not found?! Maybe check docs.microsoft.com/en-us/office/vba/language/reference/…
– jonrsharpe
Mar 7 at 17:27
And what does it return if not found?! Maybe check docs.microsoft.com/en-us/office/vba/language/reference/…
– jonrsharpe
Mar 7 at 17:27
add a comment |
3 Answers
3
active
oldest
votes
VBA/VBScript does not have real logical operators (AND, OR, NOT). The logical operators you see are actually bitwise operators, and that's all you get. VBA plays some games with the True
and False
values so this works most of the time, but occasionally you'll find a "gotcha".
In this case, instead of If Not InStr() Then
you have to write If InStr() <= 0 Then
.
Instead of If InStr() Then
you have to write If InStr() > 0 Then
In other words: InStr()
returns a number. Don't try to treat it like a boolean.
Good, concise answer - the last sentence is key.
– Mathieu Guindon
Mar 7 at 17:48
add a comment |
1
is not the integer representation of True
, -1
is.
Debug.Print CInt(True) 'prints -1
Debug.Print CInt(False) 'prints 0
Boolean operators (Not
, And
, Or
, XOr
) behave as "logical operators" when their operands are Boolean values. When they're not, they behave as "bitwise operators" but the truth is, they're always bitwise.
The integer value 1
converts to the Boolean value True
only because True
is defined as Not False
, which means any non-zero value is a Boolean True
. But you only get the correct/expected logical behavior when you use -1
for True
.
An Integer
is represented by 16 bits, so 1
is this:
0000 0000 0000 0001
This makes Not 1
this:
1111 1111 1111 1110
The sign bit is on, so the value is negative - trim the insignificant digits and you get:
10
Which is the binary representation for 2
. Hence, Not 1
is -2
.
Inversely, -1
would be:
1111 1111 1111 1111
And Not -1
is thus:
0000 0000 0000 0000
add a comment |
As the other answers have already explained about the why, I want to focus on the coding practices.
As you found out, Not x
is not necessarily what you want. In practice you want more like Not CBool(x)
. However, CBool()
can throw errors - for example, CBool(Null)
yields error 91 (invalid use of null).
It might be claimed that you can avoid this by strong-typing your variables but even not using a Variant
does not guarantee that in an expression a Boolean
will stay a Boolean
. Example:
?typename(true and 0)
Integer
In practice, it's too easy to accidentally allow VBA to do the voodoo implicit conversions for you, so for that reasons, altering coding habits might suit you better.
For testing truthy values, you want expressions like:
If x Then
And for falsy values, you want expressions like:
If x = False Then
Those works regardless of the type of the x
, whether it's an expression or not and thus is said to be much more consistent/predictable in its behavior compared to the If x = True Then
or If Not x Then
. By adopting this code habit, you can help avoid creating subtle bugs arising from accidental conversion away from Boolean
types and getting a bitwise operation rather than logical operation.
For assignments, using a Boolean
variable will work in ensuring that it's consistently coerced into either True
or False
and not some random numbers.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55049440%2fnot-1-evaluates-to-2-for-some-reason%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
VBA/VBScript does not have real logical operators (AND, OR, NOT). The logical operators you see are actually bitwise operators, and that's all you get. VBA plays some games with the True
and False
values so this works most of the time, but occasionally you'll find a "gotcha".
In this case, instead of If Not InStr() Then
you have to write If InStr() <= 0 Then
.
Instead of If InStr() Then
you have to write If InStr() > 0 Then
In other words: InStr()
returns a number. Don't try to treat it like a boolean.
Good, concise answer - the last sentence is key.
– Mathieu Guindon
Mar 7 at 17:48
add a comment |
VBA/VBScript does not have real logical operators (AND, OR, NOT). The logical operators you see are actually bitwise operators, and that's all you get. VBA plays some games with the True
and False
values so this works most of the time, but occasionally you'll find a "gotcha".
In this case, instead of If Not InStr() Then
you have to write If InStr() <= 0 Then
.
Instead of If InStr() Then
you have to write If InStr() > 0 Then
In other words: InStr()
returns a number. Don't try to treat it like a boolean.
Good, concise answer - the last sentence is key.
– Mathieu Guindon
Mar 7 at 17:48
add a comment |
VBA/VBScript does not have real logical operators (AND, OR, NOT). The logical operators you see are actually bitwise operators, and that's all you get. VBA plays some games with the True
and False
values so this works most of the time, but occasionally you'll find a "gotcha".
In this case, instead of If Not InStr() Then
you have to write If InStr() <= 0 Then
.
Instead of If InStr() Then
you have to write If InStr() > 0 Then
In other words: InStr()
returns a number. Don't try to treat it like a boolean.
VBA/VBScript does not have real logical operators (AND, OR, NOT). The logical operators you see are actually bitwise operators, and that's all you get. VBA plays some games with the True
and False
values so this works most of the time, but occasionally you'll find a "gotcha".
In this case, instead of If Not InStr() Then
you have to write If InStr() <= 0 Then
.
Instead of If InStr() Then
you have to write If InStr() > 0 Then
In other words: InStr()
returns a number. Don't try to treat it like a boolean.
edited Mar 7 at 17:45
answered Mar 7 at 17:40
Joel CoehoornJoel Coehoorn
311k96496730
311k96496730
Good, concise answer - the last sentence is key.
– Mathieu Guindon
Mar 7 at 17:48
add a comment |
Good, concise answer - the last sentence is key.
– Mathieu Guindon
Mar 7 at 17:48
Good, concise answer - the last sentence is key.
– Mathieu Guindon
Mar 7 at 17:48
Good, concise answer - the last sentence is key.
– Mathieu Guindon
Mar 7 at 17:48
add a comment |
1
is not the integer representation of True
, -1
is.
Debug.Print CInt(True) 'prints -1
Debug.Print CInt(False) 'prints 0
Boolean operators (Not
, And
, Or
, XOr
) behave as "logical operators" when their operands are Boolean values. When they're not, they behave as "bitwise operators" but the truth is, they're always bitwise.
The integer value 1
converts to the Boolean value True
only because True
is defined as Not False
, which means any non-zero value is a Boolean True
. But you only get the correct/expected logical behavior when you use -1
for True
.
An Integer
is represented by 16 bits, so 1
is this:
0000 0000 0000 0001
This makes Not 1
this:
1111 1111 1111 1110
The sign bit is on, so the value is negative - trim the insignificant digits and you get:
10
Which is the binary representation for 2
. Hence, Not 1
is -2
.
Inversely, -1
would be:
1111 1111 1111 1111
And Not -1
is thus:
0000 0000 0000 0000
add a comment |
1
is not the integer representation of True
, -1
is.
Debug.Print CInt(True) 'prints -1
Debug.Print CInt(False) 'prints 0
Boolean operators (Not
, And
, Or
, XOr
) behave as "logical operators" when their operands are Boolean values. When they're not, they behave as "bitwise operators" but the truth is, they're always bitwise.
The integer value 1
converts to the Boolean value True
only because True
is defined as Not False
, which means any non-zero value is a Boolean True
. But you only get the correct/expected logical behavior when you use -1
for True
.
An Integer
is represented by 16 bits, so 1
is this:
0000 0000 0000 0001
This makes Not 1
this:
1111 1111 1111 1110
The sign bit is on, so the value is negative - trim the insignificant digits and you get:
10
Which is the binary representation for 2
. Hence, Not 1
is -2
.
Inversely, -1
would be:
1111 1111 1111 1111
And Not -1
is thus:
0000 0000 0000 0000
add a comment |
1
is not the integer representation of True
, -1
is.
Debug.Print CInt(True) 'prints -1
Debug.Print CInt(False) 'prints 0
Boolean operators (Not
, And
, Or
, XOr
) behave as "logical operators" when their operands are Boolean values. When they're not, they behave as "bitwise operators" but the truth is, they're always bitwise.
The integer value 1
converts to the Boolean value True
only because True
is defined as Not False
, which means any non-zero value is a Boolean True
. But you only get the correct/expected logical behavior when you use -1
for True
.
An Integer
is represented by 16 bits, so 1
is this:
0000 0000 0000 0001
This makes Not 1
this:
1111 1111 1111 1110
The sign bit is on, so the value is negative - trim the insignificant digits and you get:
10
Which is the binary representation for 2
. Hence, Not 1
is -2
.
Inversely, -1
would be:
1111 1111 1111 1111
And Not -1
is thus:
0000 0000 0000 0000
1
is not the integer representation of True
, -1
is.
Debug.Print CInt(True) 'prints -1
Debug.Print CInt(False) 'prints 0
Boolean operators (Not
, And
, Or
, XOr
) behave as "logical operators" when their operands are Boolean values. When they're not, they behave as "bitwise operators" but the truth is, they're always bitwise.
The integer value 1
converts to the Boolean value True
only because True
is defined as Not False
, which means any non-zero value is a Boolean True
. But you only get the correct/expected logical behavior when you use -1
for True
.
An Integer
is represented by 16 bits, so 1
is this:
0000 0000 0000 0001
This makes Not 1
this:
1111 1111 1111 1110
The sign bit is on, so the value is negative - trim the insignificant digits and you get:
10
Which is the binary representation for 2
. Hence, Not 1
is -2
.
Inversely, -1
would be:
1111 1111 1111 1111
And Not -1
is thus:
0000 0000 0000 0000
edited Mar 7 at 17:58
answered Mar 7 at 17:40
Mathieu GuindonMathieu Guindon
44.2k769151
44.2k769151
add a comment |
add a comment |
As the other answers have already explained about the why, I want to focus on the coding practices.
As you found out, Not x
is not necessarily what you want. In practice you want more like Not CBool(x)
. However, CBool()
can throw errors - for example, CBool(Null)
yields error 91 (invalid use of null).
It might be claimed that you can avoid this by strong-typing your variables but even not using a Variant
does not guarantee that in an expression a Boolean
will stay a Boolean
. Example:
?typename(true and 0)
Integer
In practice, it's too easy to accidentally allow VBA to do the voodoo implicit conversions for you, so for that reasons, altering coding habits might suit you better.
For testing truthy values, you want expressions like:
If x Then
And for falsy values, you want expressions like:
If x = False Then
Those works regardless of the type of the x
, whether it's an expression or not and thus is said to be much more consistent/predictable in its behavior compared to the If x = True Then
or If Not x Then
. By adopting this code habit, you can help avoid creating subtle bugs arising from accidental conversion away from Boolean
types and getting a bitwise operation rather than logical operation.
For assignments, using a Boolean
variable will work in ensuring that it's consistently coerced into either True
or False
and not some random numbers.
add a comment |
As the other answers have already explained about the why, I want to focus on the coding practices.
As you found out, Not x
is not necessarily what you want. In practice you want more like Not CBool(x)
. However, CBool()
can throw errors - for example, CBool(Null)
yields error 91 (invalid use of null).
It might be claimed that you can avoid this by strong-typing your variables but even not using a Variant
does not guarantee that in an expression a Boolean
will stay a Boolean
. Example:
?typename(true and 0)
Integer
In practice, it's too easy to accidentally allow VBA to do the voodoo implicit conversions for you, so for that reasons, altering coding habits might suit you better.
For testing truthy values, you want expressions like:
If x Then
And for falsy values, you want expressions like:
If x = False Then
Those works regardless of the type of the x
, whether it's an expression or not and thus is said to be much more consistent/predictable in its behavior compared to the If x = True Then
or If Not x Then
. By adopting this code habit, you can help avoid creating subtle bugs arising from accidental conversion away from Boolean
types and getting a bitwise operation rather than logical operation.
For assignments, using a Boolean
variable will work in ensuring that it's consistently coerced into either True
or False
and not some random numbers.
add a comment |
As the other answers have already explained about the why, I want to focus on the coding practices.
As you found out, Not x
is not necessarily what you want. In practice you want more like Not CBool(x)
. However, CBool()
can throw errors - for example, CBool(Null)
yields error 91 (invalid use of null).
It might be claimed that you can avoid this by strong-typing your variables but even not using a Variant
does not guarantee that in an expression a Boolean
will stay a Boolean
. Example:
?typename(true and 0)
Integer
In practice, it's too easy to accidentally allow VBA to do the voodoo implicit conversions for you, so for that reasons, altering coding habits might suit you better.
For testing truthy values, you want expressions like:
If x Then
And for falsy values, you want expressions like:
If x = False Then
Those works regardless of the type of the x
, whether it's an expression or not and thus is said to be much more consistent/predictable in its behavior compared to the If x = True Then
or If Not x Then
. By adopting this code habit, you can help avoid creating subtle bugs arising from accidental conversion away from Boolean
types and getting a bitwise operation rather than logical operation.
For assignments, using a Boolean
variable will work in ensuring that it's consistently coerced into either True
or False
and not some random numbers.
As the other answers have already explained about the why, I want to focus on the coding practices.
As you found out, Not x
is not necessarily what you want. In practice you want more like Not CBool(x)
. However, CBool()
can throw errors - for example, CBool(Null)
yields error 91 (invalid use of null).
It might be claimed that you can avoid this by strong-typing your variables but even not using a Variant
does not guarantee that in an expression a Boolean
will stay a Boolean
. Example:
?typename(true and 0)
Integer
In practice, it's too easy to accidentally allow VBA to do the voodoo implicit conversions for you, so for that reasons, altering coding habits might suit you better.
For testing truthy values, you want expressions like:
If x Then
And for falsy values, you want expressions like:
If x = False Then
Those works regardless of the type of the x
, whether it's an expression or not and thus is said to be much more consistent/predictable in its behavior compared to the If x = True Then
or If Not x Then
. By adopting this code habit, you can help avoid creating subtle bugs arising from accidental conversion away from Boolean
types and getting a bitwise operation rather than logical operation.
For assignments, using a Boolean
variable will work in ensuring that it's consistently coerced into either True
or False
and not some random numbers.
answered Mar 7 at 18:01
thisthis
742614
742614
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55049440%2fnot-1-evaluates-to-2-for-some-reason%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Two's complement? In (8-bit) binary, 1 is
00000001
and -2 is11111110
, you're doing a bitwise not.– jonrsharpe
Mar 7 at 17:16
So how do I stop doing a bitwise not? InStr returns a position in a string and I need to take action if a string is not found, ie If Not InStr....
– public wireless
Mar 7 at 17:23
Well what value do you get if it's not found? Check for that.
– jonrsharpe
Mar 7 at 17:24
InStr returns some index greater than 0 if found, and applying Not makes the value -2. Thus because the value is -2 and not 0, my if statement doesn't work
– public wireless
Mar 7 at 17:26
2
And what does it return if not found?! Maybe check docs.microsoft.com/en-us/office/vba/language/reference/…
– jonrsharpe
Mar 7 at 17:27